1; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
2
3target triple = "wasm32-unknown-unknown"
4
5; Return multiple values, some of which will be legalized into multiple values.
6declare { i64, i128, i192, i128, i64 } @return_multi_multi()
7
8; Test returning a single value from @return_multi_multi.
9
10define i64 @test0() {
11; CHECK-LABEL: test0:
12; CHECK: call    	return_multi_multi
13; CHECK: i64.load	$[[RV:[0-9]+]]=, 8(${{[0-9]+}})
14; CHECK: local.copy	$push8=, $[[RV]]
15  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
16  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
17  ret i64 %t1
18}
19
20define i128 @test1() {
21; CHECK-LABEL: test1:
22; CHECK: call    	return_multi_multi
23; CHECK: i64.load	$[[RV:[0-9]+]]=, 16($[[SP:[0-9]+]])
24; CHECK: i32.const	$push0=, 24
25; CHECK: i32.add 	$push1=, $[[SP]], $pop0
26; CHECK: i64.load	$push2=, 0($pop1)
27; CHECK: i64.store	8($0), $pop2
28; CHECK: i64.store	0($0), $[[RV]]
29  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
30  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
31  ret i128 %t1
32}
33
34define i192 @test2() {
35; CHECK-LABEL: test2:
36; CHECK: call    	return_multi_multi
37; CHECK: i32.const	$push0=, 40
38; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
39; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
40; CHECK: i64.load	$[[L2:[0-9]+]]=, 32($[[SP]])
41; CHECK: i32.const	$push2=, 48
42; CHECK: i32.add 	$push3=, $[[SP]], $pop2
43; CHECK: i64.load	$push4=, 0($pop3)
44; CHECK: i64.store	16($0), $pop4
45; CHECK: i64.store	0($0), $[[L2]]
46; CHECK: i64.store	8($0), $[[L1]]
47  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
48  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
49  ret i192 %t1
50}
51
52define i128 @test3() {
53; CHECK-LABEL: test3:
54; CHECK: call    	return_multi_multi
55; CHECK: i64.load	$[[L1:[0-9]+]]=, 56($[[SP:[0-9]+]])
56; CHECK: i32.const	$push0=, 64
57; CHECK: i32.add 	$push1=, $[[SP]], $pop0
58; CHECK: i64.load	$push2=, 0($pop1)
59; CHECK: i64.store	8($0), $pop2
60; CHECK: i64.store	0($0), $[[L1]]
61  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
62  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
63  ret i128 %t1
64}
65
66define i64 @test4() {
67; CHECK-LABEL: test4:
68; CHECK: call    	return_multi_multi
69; CHECK: i64.load	$[[L1:[0-9]+]]=, 72($[[SP:[0-9]+]])
70; CHECK: local.copy	$push8=, $[[L1]]
71  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
72  %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4
73  ret i64 %t1
74}
75
76; Test returning multiple values from @return_multi_multi.
77
78define { i64, i128 } @test5() {
79; CHECK-LABEL: test5:
80; CHECK: call    	return_multi_multi
81; CHECK: i32.const	$push10=, 8
82; CHECK: i32.add 	$push11=, $[[SP:[0-9]+]], $pop10
83; CHECK: i32.const	$push0=, 16
84; CHECK: i32.add 	$push1=, $pop11, $pop0
85; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
86; CHECK: i64.load	$[[L2:[0-9]+]]=, 8($[[SP]])
87; CHECK: i64.load	$push2=, 16($[[SP]])
88; CHECK: i64.store	8($0), $pop2
89; CHECK: i64.store	0($0), $[[L2]]
90; CHECK: i32.const	$push12=, 16
91; CHECK: i32.add 	$push3=, $0, $pop12
92; CHECK: i64.store	0($pop3), $[[L1]]
93  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
94  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
95  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
96  %s0 = insertvalue { i64, i128 } undef, i64 %r0, 0
97  %s1 = insertvalue { i64, i128 } %s0, i128 %r1, 1
98  ret { i64, i128 } %s1
99}
100
101define { i128, i128 } @test6() {
102; CHECK-LABEL: test6:
103; CHECK: call    	return_multi_multi
104; CHECK: i32.const	$push0=, 64
105; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
106; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
107; CHECK: i32.const	$push2=, 24
108; CHECK: i32.add 	$push3=, $[[SP]], $pop2
109; CHECK: i64.load	$[[L2:[0-9]+]]=, 0($pop3)
110; CHECK: i64.load	$[[L3:[0-9]+]]=, 16($[[SP]])
111; CHECK: i64.load	$push4=, 56($[[SP]])
112; CHECK: i64.store	16($0), $pop4
113; CHECK: i64.store	0($0), $[[L3]]
114; CHECK: i64.store	8($0), $[[L2]]
115; CHECK: i32.const	$push5=, 24
116; CHECK: i32.add 	$push6=, $0, $pop5
117; CHECK: i64.store	0($pop6), $[[L1]]
118  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
119  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
120  %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
121  %s0 = insertvalue { i128, i128 } undef, i128 %r1, 0
122  %s1 = insertvalue { i128, i128 } %s0, i128 %r3, 1
123  ret { i128, i128 } %s1
124}
125
126define { i64, i192 } @test7() {
127; CHECK-LABEL: test7:
128; CHECK: call    	return_multi_multi
129; CHECK: i32.const	$push0=, 40
130; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
131; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
132; CHECK: i32.const	$push2=, 48
133; CHECK: i32.add 	$push3=, $[[SP]], $pop2
134; CHECK: i64.load	$[[L2:[0-9]+]]=, 0($pop3)
135; CHECK: i64.load	$[[L3:[0-9]+]]=, 8($[[SP]])
136; CHECK: i64.load	$push4=, 32($[[SP]])
137; CHECK: i64.store	8($0), $pop4
138; CHECK: i64.store	0($0), $[[L3]]
139; CHECK: i32.const	$push5=, 24
140; CHECK: i32.add 	$push6=, $0, $pop5
141; CHECK: i64.store	0($pop6), $[[L2]]
142; CHECK: i32.const	$push7=, 16
143; CHECK: i32.add 	$push8=, $0, $pop7
144; CHECK: i64.store	0($pop8), $[[L1]]
145  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
146  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
147  %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
148  %s0 = insertvalue { i64, i192 } undef, i64 %r0, 0
149  %s1 = insertvalue { i64, i192 } %s0, i192 %r2, 1
150  ret { i64, i192 } %s1
151}
152
153define { i128, i192, i128, i64 } @test8() {
154; CHECK-LABEL: test8:
155; CHECK: call    	return_multi_multi
156; CHECK: i32.const	$push20=, 8
157; CHECK: i32.add 	$push21=, $[[SP:[0-9]+]], $pop20
158; CHECK: i32.const	$push0=, 32
159; CHECK: i32.add 	$push1=, $pop21, $pop0
160; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
161; CHECK: i32.const	$push2=, 48
162; CHECK: i32.add 	$push3=, $[[SP]], $pop2
163; CHECK: i64.load	$[[L2:[0-9]+]]=, 0($pop3)
164; CHECK: i32.const	$push4=, 24
165; CHECK: i32.add 	$push5=, $[[SP]], $pop4
166; CHECK: i64.load	$[[L3:[0-9]+]]=, 0($pop5)
167; CHECK: i32.const	$push6=, 64
168; CHECK: i32.add 	$push7=, $[[SP]], $pop6
169; CHECK: i64.load	$[[L4:[0-9]+]]=, 0($pop7)
170; CHECK: i64.load	$[[L5:[0-9]+]]=, 8($[[SP]])
171; CHECK: i64.load	$[[L6:[0-9]+]]=, 56($[[SP]])
172; CHECK: i64.load	$[[L7:[0-9]+]]=, 32($[[SP]])
173; CHECK: i64.load	$push8=, 16($[[SP]])
174; CHECK: i64.store	40($0), $pop8
175; CHECK: i64.store	16($0), $[[L7]]
176; CHECK: i64.store	0($0), $[[L6]]
177; CHECK: i64.store	8($0), $[[L4]]
178; CHECK: i64.store	56($0), $[[L5]]
179; CHECK: i32.const	$push9=, 48
180; CHECK: i32.add 	$push10=, $0, $pop9
181; CHECK: i64.store	0($pop10), $[[L3]]
182; CHECK: i32.const	$push22=, 32
183; CHECK: i32.add 	$push11=, $0, $pop22
184; CHECK: i64.store	0($pop11), $[[L2]]
185; CHECK: i32.const	$push12=, 24
186; CHECK: i32.add 	$push13=, $0, $pop12
187; CHECK: i64.store	0($pop13), $[[L1]]
188  %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
189  %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
190  %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
191  %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
192  %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
193  %s0 = insertvalue { i128, i192, i128, i64 } undef, i128 %r3, 0
194  %s1 = insertvalue { i128, i192, i128, i64 } %s0, i192 %r2, 1
195  %s2 = insertvalue { i128, i192, i128, i64 } %s1, i128 %r1, 2
196  %s3 = insertvalue { i128, i192, i128, i64 } %s2, i64 %r0, 3
197  ret { i128, i192, i128, i64 } %s3
198}
199