xref: /llvm-project/llvm/test/CodeGen/WebAssembly/multi-return.ll (revision c5ab70c508457eaece5d7ff4ab79a2f90bc67f06)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2; RUN: llc < %s -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
3
4target triple = "wasm32-unknown-unknown"
5
6; Return multiple values, some of which will be legalized into multiple values.
7declare { i64, i128, i192, i128, i64 } @return_multi_multi()
8
9; Test returning a single value from @return_multi_multi.
10
11define i64 @test0() {
12; CHECK-LABEL: test0:
13; CHECK:         .functype test0 () -> (i64)
14; CHECK-NEXT:  # %bb.0:
15; CHECK-NEXT:    global.get $push0=, __stack_pointer
16; CHECK-NEXT:    i32.const $push1=, 96
17; CHECK-NEXT:    i32.sub $push5=, $pop0, $pop1
18; CHECK-NEXT:    local.tee $push4=, $1=, $pop5
19; CHECK-NEXT:    global.set __stack_pointer, $pop4
20; CHECK-NEXT:    call return_multi_multi, $1
21; CHECK-NEXT:    i64.load $0=, 0($1)
22; CHECK-NEXT:    i32.const $push2=, 96
23; CHECK-NEXT:    i32.add $push3=, $1, $pop2
24; CHECK-NEXT:    global.set __stack_pointer, $pop3
25; CHECK-NEXT:    local.copy $push6=, $0
26; CHECK-NEXT:    # fallthrough-return
27  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
28  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
29  ret i64 %t1
30}
31
32define i128 @test1() {
33; CHECK-LABEL: test1:
34; CHECK:         .functype test1 (i32) -> ()
35; CHECK-NEXT:  # %bb.0:
36; CHECK-NEXT:    global.get $push1=, __stack_pointer
37; CHECK-NEXT:    i32.const $push2=, 96
38; CHECK-NEXT:    i32.sub $push6=, $pop1, $pop2
39; CHECK-NEXT:    local.tee $push5=, $2=, $pop6
40; CHECK-NEXT:    global.set __stack_pointer, $pop5
41; CHECK-NEXT:    call return_multi_multi, $2
42; CHECK-NEXT:    i64.load $1=, 24($2)
43; CHECK-NEXT:    i64.load $push0=, 16($2)
44; CHECK-NEXT:    i64.store 0($0), $pop0
45; CHECK-NEXT:    i64.store 8($0), $1
46; CHECK-NEXT:    i32.const $push3=, 96
47; CHECK-NEXT:    i32.add $push4=, $2, $pop3
48; CHECK-NEXT:    global.set __stack_pointer, $pop4
49; CHECK-NEXT:    # fallthrough-return
50  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
51  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
52  ret i128 %t1
53}
54
55define i192 @test2() {
56; CHECK-LABEL: test2:
57; CHECK:         .functype test2 (i32) -> ()
58; CHECK-NEXT:  # %bb.0:
59; CHECK-NEXT:    global.get $push3=, __stack_pointer
60; CHECK-NEXT:    i32.const $push4=, 96
61; CHECK-NEXT:    i32.sub $push8=, $pop3, $pop4
62; CHECK-NEXT:    local.tee $push7=, $3=, $pop8
63; CHECK-NEXT:    global.set __stack_pointer, $pop7
64; CHECK-NEXT:    call return_multi_multi, $3
65; CHECK-NEXT:    i64.load $1=, 40($3)
66; CHECK-NEXT:    i64.load $2=, 32($3)
67; CHECK-NEXT:    i32.const $push0=, 48
68; CHECK-NEXT:    i32.add $push1=, $3, $pop0
69; CHECK-NEXT:    i64.load $push2=, 0($pop1)
70; CHECK-NEXT:    i64.store 16($0), $pop2
71; CHECK-NEXT:    i64.store 0($0), $2
72; CHECK-NEXT:    i64.store 8($0), $1
73; CHECK-NEXT:    i32.const $push5=, 96
74; CHECK-NEXT:    i32.add $push6=, $3, $pop5
75; CHECK-NEXT:    global.set __stack_pointer, $pop6
76; CHECK-NEXT:    # fallthrough-return
77  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
78  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
79  ret i192 %t1
80}
81
82define i128 @test3() {
83; CHECK-LABEL: test3:
84; CHECK:         .functype test3 (i32) -> ()
85; CHECK-NEXT:  # %bb.0:
86; CHECK-NEXT:    global.get $push1=, __stack_pointer
87; CHECK-NEXT:    i32.const $push2=, 96
88; CHECK-NEXT:    i32.sub $push6=, $pop1, $pop2
89; CHECK-NEXT:    local.tee $push5=, $2=, $pop6
90; CHECK-NEXT:    global.set __stack_pointer, $pop5
91; CHECK-NEXT:    call return_multi_multi, $2
92; CHECK-NEXT:    i64.load $1=, 72($2)
93; CHECK-NEXT:    i64.load $push0=, 64($2)
94; CHECK-NEXT:    i64.store 0($0), $pop0
95; CHECK-NEXT:    i64.store 8($0), $1
96; CHECK-NEXT:    i32.const $push3=, 96
97; CHECK-NEXT:    i32.add $push4=, $2, $pop3
98; CHECK-NEXT:    global.set __stack_pointer, $pop4
99; CHECK-NEXT:    # fallthrough-return
100  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
101  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
102  ret i128 %t1
103}
104
105define i64 @test4() {
106; CHECK-LABEL: test4:
107; CHECK:         .functype test4 () -> (i64)
108; CHECK-NEXT:  # %bb.0:
109; CHECK-NEXT:    global.get $push0=, __stack_pointer
110; CHECK-NEXT:    i32.const $push1=, 96
111; CHECK-NEXT:    i32.sub $push5=, $pop0, $pop1
112; CHECK-NEXT:    local.tee $push4=, $1=, $pop5
113; CHECK-NEXT:    global.set __stack_pointer, $pop4
114; CHECK-NEXT:    call return_multi_multi, $1
115; CHECK-NEXT:    i64.load $0=, 80($1)
116; CHECK-NEXT:    i32.const $push2=, 96
117; CHECK-NEXT:    i32.add $push3=, $1, $pop2
118; CHECK-NEXT:    global.set __stack_pointer, $pop3
119; CHECK-NEXT:    local.copy $push6=, $0
120; CHECK-NEXT:    # fallthrough-return
121  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
122  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4
123  ret i64 %t1
124}
125
126; Test returning multiple values from @return_multi_multi.
127
128define { i64, i128 } @test5() {
129; CHECK-LABEL: test5:
130; CHECK:         .functype test5 (i32) -> ()
131; CHECK-NEXT:  # %bb.0:
132; CHECK-NEXT:    global.get $push1=, __stack_pointer
133; CHECK-NEXT:    i32.const $push2=, 96
134; CHECK-NEXT:    i32.sub $push6=, $pop1, $pop2
135; CHECK-NEXT:    local.tee $push5=, $3=, $pop6
136; CHECK-NEXT:    global.set __stack_pointer, $pop5
137; CHECK-NEXT:    call return_multi_multi, $3
138; CHECK-NEXT:    i64.load $1=, 24($3)
139; CHECK-NEXT:    i64.load $2=, 16($3)
140; CHECK-NEXT:    i64.load $push0=, 0($3)
141; CHECK-NEXT:    i64.store 0($0), $pop0
142; CHECK-NEXT:    i64.store 16($0), $2
143; CHECK-NEXT:    i64.store 24($0), $1
144; CHECK-NEXT:    i32.const $push3=, 96
145; CHECK-NEXT:    i32.add $push4=, $3, $pop3
146; CHECK-NEXT:    global.set __stack_pointer, $pop4
147; CHECK-NEXT:    # fallthrough-return
148  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
149  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
150  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
151  %s0 = insertvalue { i64, i128 } undef, i64 %r0, 0
152  %s1 = insertvalue { i64, i128 } %s0, i128 %r1, 1
153  ret { i64, i128 } %s1
154}
155
156define { i128, i128 } @test6() {
157; CHECK-LABEL: test6:
158; CHECK:         .functype test6 (i32) -> ()
159; CHECK-NEXT:  # %bb.0:
160; CHECK-NEXT:    global.get $push1=, __stack_pointer
161; CHECK-NEXT:    i32.const $push2=, 96
162; CHECK-NEXT:    i32.sub $push6=, $pop1, $pop2
163; CHECK-NEXT:    local.tee $push5=, $4=, $pop6
164; CHECK-NEXT:    global.set __stack_pointer, $pop5
165; CHECK-NEXT:    call return_multi_multi, $4
166; CHECK-NEXT:    i64.load $1=, 24($4)
167; CHECK-NEXT:    i64.load $2=, 16($4)
168; CHECK-NEXT:    i64.load $3=, 72($4)
169; CHECK-NEXT:    i64.load $push0=, 64($4)
170; CHECK-NEXT:    i64.store 16($0), $pop0
171; CHECK-NEXT:    i64.store 24($0), $3
172; CHECK-NEXT:    i64.store 0($0), $2
173; CHECK-NEXT:    i64.store 8($0), $1
174; CHECK-NEXT:    i32.const $push3=, 96
175; CHECK-NEXT:    i32.add $push4=, $4, $pop3
176; CHECK-NEXT:    global.set __stack_pointer, $pop4
177; CHECK-NEXT:    # fallthrough-return
178  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
179  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
180  %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
181  %s0 = insertvalue { i128, i128 } undef, i128 %r1, 0
182  %s1 = insertvalue { i128, i128 } %s0, i128 %r3, 1
183  ret { i128, i128 } %s1
184}
185
186define { i64, i192 } @test7() {
187; CHECK-LABEL: test7:
188; CHECK:         .functype test7 (i32) -> ()
189; CHECK-NEXT:  # %bb.0:
190; CHECK-NEXT:    global.get $push3=, __stack_pointer
191; CHECK-NEXT:    i32.const $push4=, 96
192; CHECK-NEXT:    i32.sub $push8=, $pop3, $pop4
193; CHECK-NEXT:    local.tee $push7=, $4=, $pop8
194; CHECK-NEXT:    global.set __stack_pointer, $pop7
195; CHECK-NEXT:    call return_multi_multi, $4
196; CHECK-NEXT:    i32.const $push0=, 48
197; CHECK-NEXT:    i32.add $push1=, $4, $pop0
198; CHECK-NEXT:    i64.load $1=, 0($pop1)
199; CHECK-NEXT:    i64.load $2=, 40($4)
200; CHECK-NEXT:    i64.load $3=, 32($4)
201; CHECK-NEXT:    i64.load $push2=, 0($4)
202; CHECK-NEXT:    i64.store 0($0), $pop2
203; CHECK-NEXT:    i64.store 32($0), $1
204; CHECK-NEXT:    i64.store 16($0), $3
205; CHECK-NEXT:    i64.store 24($0), $2
206; CHECK-NEXT:    i32.const $push5=, 96
207; CHECK-NEXT:    i32.add $push6=, $4, $pop5
208; CHECK-NEXT:    global.set __stack_pointer, $pop6
209; CHECK-NEXT:    # fallthrough-return
210  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
211  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
212  %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
213  %s0 = insertvalue { i64, i192 } undef, i64 %r0, 0
214  %s1 = insertvalue { i64, i192 } %s0, i192 %r2, 1
215  ret { i64, i192 } %s1
216}
217
218define { i128, i192, i128, i64 } @test8() {
219; CHECK-LABEL: test8:
220; CHECK:         .functype test8 (i32) -> ()
221; CHECK-NEXT:  # %bb.0:
222; CHECK-NEXT:    global.get $push3=, __stack_pointer
223; CHECK-NEXT:    i32.const $push4=, 96
224; CHECK-NEXT:    i32.sub $push8=, $pop3, $pop4
225; CHECK-NEXT:    local.tee $push7=, $8=, $pop8
226; CHECK-NEXT:    global.set __stack_pointer, $pop7
227; CHECK-NEXT:    call return_multi_multi, $8
228; CHECK-NEXT:    i32.const $push0=, 48
229; CHECK-NEXT:    i32.add $push1=, $8, $pop0
230; CHECK-NEXT:    i64.load $1=, 0($pop1)
231; CHECK-NEXT:    i64.load $2=, 72($8)
232; CHECK-NEXT:    i64.load $3=, 64($8)
233; CHECK-NEXT:    i64.load $4=, 40($8)
234; CHECK-NEXT:    i64.load $5=, 32($8)
235; CHECK-NEXT:    i64.load $6=, 24($8)
236; CHECK-NEXT:    i64.load $7=, 16($8)
237; CHECK-NEXT:    i64.load $push2=, 0($8)
238; CHECK-NEXT:    i64.store 64($0), $pop2
239; CHECK-NEXT:    i64.store 48($0), $7
240; CHECK-NEXT:    i64.store 56($0), $6
241; CHECK-NEXT:    i64.store 32($0), $1
242; CHECK-NEXT:    i64.store 16($0), $5
243; CHECK-NEXT:    i64.store 24($0), $4
244; CHECK-NEXT:    i64.store 0($0), $3
245; CHECK-NEXT:    i64.store 8($0), $2
246; CHECK-NEXT:    i32.const $push5=, 96
247; CHECK-NEXT:    i32.add $push6=, $8, $pop5
248; CHECK-NEXT:    global.set __stack_pointer, $pop6
249; CHECK-NEXT:    # fallthrough-return
250  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
251  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
252  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
253  %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
254  %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
255  %s0 = insertvalue { i128, i192, i128, i64 } undef, i128 %r3, 0
256  %s1 = insertvalue { i128, i192, i128, i64 } %s0, i192 %r2, 1
257  %s2 = insertvalue { i128, i192, i128, i64 } %s1, i128 %r1, 2
258  %s3 = insertvalue { i128, i192, i128, i64 } %s2, i64 %r0, 3
259  ret { i128, i192, i128, i64 } %s3
260}
261