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