1; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
2; RUN: llc -O0 -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s --check-prefix=CHECK-O0
3
4; CHECK-LABEL: test1
5; CHECK: bl      _gen
6; CHECK: sxth    [[TMP:w.*]], w0
7; CHECK: add     w0, [[TMP]], w1, sxtb
8; CHECK-O0-LABEL: test1
9; CHECK-O0: bl      _gen
10; CHECK-O0: sxth    [[TMP:w.*]], w0
11; CHECK-O0: add     w0, [[TMP]], w1, sxtb
12define i16 @test1(i32) {
13entry:
14  %call = call swiftcc { i16, i8 } @gen(i32 %0)
15  %v3 = extractvalue { i16, i8 } %call, 0
16  %v1 = sext i16 %v3 to i32
17  %v5 = extractvalue { i16, i8 } %call, 1
18  %v2 = sext i8 %v5 to i32
19  %add = add nsw i32 %v1, %v2
20  %conv = trunc i32 %add to i16
21  ret i16 %conv
22}
23
24declare swiftcc { i16, i8 } @gen(i32)
25
26; CHECK-LABEL: test2
27; CHECK:  bl      _gen2
28; CHECK:  add     [[TMP:x.*]], x0, x1
29; CHECK:  add     [[TMP]], [[TMP]], x2
30; CHECK:  add     [[TMP]], [[TMP]], x3
31; CHECK:  add     x0, [[TMP]], x4
32; CHECK-O0-LABEL: test2
33; CHECK-O0:  bl      _gen2
34; CHECK-O0:  add     [[TMP:x.*]], x0, x1
35; CHECK-O0:  add     [[TMP]], [[TMP]], x2
36; CHECK-O0:  add     [[TMP]], [[TMP]], x3
37; CHECK-O0:  add     x0, [[TMP]], x4
38
39define i64 @test2(i64 %key) {
40entry:
41  %key.addr = alloca i64, align 4
42  store i64 %key, i64* %key.addr, align 4
43  %0 = load i64, i64* %key.addr, align 4
44  %call = call swiftcc { i64, i64, i64, i64, i64 } @gen2(i64 %0)
45
46  %v3 = extractvalue { i64, i64, i64, i64, i64 } %call, 0
47  %v5 = extractvalue { i64, i64, i64, i64, i64 } %call, 1
48  %v6 = extractvalue { i64, i64, i64, i64, i64 } %call, 2
49  %v7 = extractvalue { i64, i64, i64, i64, i64 } %call, 3
50  %v8 = extractvalue { i64, i64, i64, i64, i64 } %call, 4
51
52  %add = add nsw i64 %v3, %v5
53  %add1 = add nsw i64 %add, %v6
54  %add2 = add nsw i64 %add1, %v7
55  %add3 = add nsw i64 %add2, %v8
56  ret i64 %add3
57}
58; CHECK-LABEL: gen2:
59; CHECK:  mov      x1, x0
60; CHECK:  mov      x2, x0
61; CHECK:  mov      x3, x0
62; CHECK:  mov      x4, x0
63; CHECK:  ret
64define swiftcc { i64, i64, i64, i64, i64 } @gen2(i64 %key) {
65  %Y = insertvalue { i64, i64, i64, i64, i64 } undef, i64 %key, 0
66  %Z = insertvalue { i64, i64, i64, i64, i64 } %Y, i64 %key, 1
67  %Z2 = insertvalue { i64, i64, i64, i64, i64 } %Z, i64 %key, 2
68  %Z3 = insertvalue { i64, i64, i64, i64, i64 } %Z2, i64 %key, 3
69  %Z4 = insertvalue { i64, i64, i64, i64, i64 } %Z3, i64 %key, 4
70  ret { i64, i64, i64, i64, i64 } %Z4
71}
72
73; CHECK-LABEL: test3
74; CHECK: bl      _gen3
75; CHECK: add             [[TMP:w.*]], w0, w1
76; CHECK: add             [[TMP]], [[TMP]], w2
77; CHECK: add             w0, [[TMP]], w3
78; CHECK-O0-LABEL: test3
79; CHECK-O0: bl      _gen3
80; CHECK-O0: add             [[TMP:w.*]], w0, w1
81; CHECK-O0: add             [[TMP]], [[TMP]], w2
82; CHECK-O0: add             w0, [[TMP]], w3
83define i32 @test3(i32) {
84entry:
85  %call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0)
86
87  %v3 = extractvalue { i32, i32, i32, i32 } %call, 0
88  %v5 = extractvalue { i32, i32, i32, i32 } %call, 1
89  %v6 = extractvalue { i32, i32, i32, i32 } %call, 2
90  %v7 = extractvalue { i32, i32, i32, i32 } %call, 3
91
92  %add = add nsw i32 %v3, %v5
93  %add1 = add nsw i32 %add, %v6
94  %add2 = add nsw i32 %add1, %v7
95  ret i32 %add2
96}
97
98declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key)
99
100; CHECK-LABEL: test4
101; CHECK: bl      _gen4
102; CHECK: fadd    s0, s0, s1
103; CHECK: fadd    s0, s0, s2
104; CHECK: fadd    s0, s0, s3
105; CHECK-O0-LABEL: test4
106; CHECK-O0: bl      _gen4
107; CHECK-O0: fadd    s0, s0, s1
108; CHECK-O0: fadd    s0, s0, s2
109; CHECK-O0: fadd    s0, s0, s3
110define float @test4(float) {
111entry:
112  %call = call swiftcc { float, float, float, float } @gen4(float %0)
113
114  %v3 = extractvalue { float, float, float, float } %call, 0
115  %v5 = extractvalue { float, float, float, float } %call, 1
116  %v6 = extractvalue { float, float, float, float } %call, 2
117  %v7 = extractvalue { float, float, float, float } %call, 3
118
119  %add = fadd float %v3, %v5
120  %add1 = fadd float %add, %v6
121  %add2 = fadd float %add1, %v7
122  ret float %add2
123}
124
125declare swiftcc { float, float, float, float } @gen4(float %key)
126
127; CHECK-LABEL: test5
128; CHECK:  bl      _gen5
129; CHECK:  fadd    d0, d0, d1
130; CHECK:  fadd    d0, d0, d2
131; CHECK:  fadd    d0, d0, d3
132; CHECK-O0-LABEL: test5
133; CHECK-O0:  bl      _gen5
134; CHECK-O0:  fadd    d0, d0, d1
135; CHECK-O0:  fadd    d0, d0, d2
136; CHECK-O0:  fadd    d0, d0, d3
137define swiftcc double @test5(){
138entry:
139  %call = call swiftcc { double, double, double, double } @gen5()
140
141  %v3 = extractvalue { double, double, double, double } %call, 0
142  %v5 = extractvalue { double, double, double, double } %call, 1
143  %v6 = extractvalue { double, double, double, double } %call, 2
144  %v7 = extractvalue { double, double, double, double } %call, 3
145
146  %add = fadd double %v3, %v5
147  %add1 = fadd double %add, %v6
148  %add2 = fadd double %add1, %v7
149  ret double %add2
150}
151
152declare swiftcc { double, double, double, double } @gen5()
153
154; CHECK-LABEL: test6
155; CHECK:   bl      _gen6
156; CHECK-DAG:   fadd    d0, d0, d1
157; CHECK-DAG:   fadd    d0, d0, d2
158; CHECK-DAG:   fadd    d0, d0, d3
159; CHECK-DAG:   add     [[TMP:w.*]], w0, w1
160; CHECK-DAG:   add     [[TMP]], [[TMP]], w2
161; CHECK-DAG:   add     w0, [[TMP]], w3
162; CHECK-O0-LABEL: test6
163; CHECK-O0:   bl      _gen6
164; CHECK-O0-DAG:   fadd    d0, d0, d1
165; CHECK-O0-DAG:   fadd    d0, d0, d2
166; CHECK-O0-DAG:   fadd    d0, d0, d3
167; CHECK-O0-DAG:   add     [[TMP:w.*]], w0, w1
168; CHECK-O0-DAG:   add     [[TMP]], [[TMP]], w2
169; CHECK-O0-DAG:   add     w0, [[TMP]], w3
170define swiftcc { double, i32 } @test6() {
171entry:
172  %call = call swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen6()
173
174  %v3 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 0
175  %v5 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 1
176  %v6 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 2
177  %v7 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 3
178  %v3.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 4
179  %v5.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 5
180  %v6.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 6
181  %v7.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 7
182
183  %add = fadd double %v3, %v5
184  %add1 = fadd double %add, %v6
185  %add2 = fadd double %add1, %v7
186
187  %add.i = add nsw i32 %v3.i, %v5.i
188  %add1.i = add nsw i32 %add.i, %v6.i
189  %add2.i = add nsw i32 %add1.i, %v7.i
190
191  %Y = insertvalue { double, i32 } undef, double %add2, 0
192  %Z = insertvalue { double, i32 } %Y, i32 %add2.i, 1
193  ret { double, i32} %Z
194}
195
196declare swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen6()
197
198; CHECK-LABEL: _gen7
199; CHECK-DAG:   mov      w1, w0
200; CHECK-DAG:   mov      w2, w0
201; CHECK-DAG:   mov      w3, w0
202; CHECK:   ret
203; CHECK-O0-LABEL: _gen7
204; CHECK-O0:  str     w0, [sp, #12]
205; CHECK-O0:  ldr     w1, [sp, #12]
206; CHECK-O0:  ldr     w2, [sp, #12]
207; CHECK-O0:  ldr     w3, [sp, #12]
208define swiftcc { i32, i32, i32, i32 } @gen7(i32 %key) {
209  %v0 = insertvalue { i32, i32, i32, i32 } undef, i32 %key, 0
210  %v1 = insertvalue { i32, i32, i32, i32 } %v0, i32 %key, 1
211  %v2 = insertvalue { i32, i32, i32, i32 } %v1, i32 %key, 2
212  %v3 = insertvalue { i32, i32, i32, i32 } %v2, i32 %key, 3
213  ret { i32, i32, i32, i32 } %v3
214}
215
216; CHECK-LABEL: _gen9
217; CHECK:  mov      w1, w0
218; CHECK:  mov      w2, w0
219; CHECK:  mov      w3, w0
220; CHECK:  ret
221; CHECK-O0-LABEL: _gen9
222; CHECK-O0:  str     w0, [sp, #12]
223; CHECK-O0:  ldr     w1, [sp, #12]
224; CHECK-O0:  ldr     w2, [sp, #12]
225; CHECK-O0:  ldr     w3, [sp, #12]
226define swiftcc { i8, i8, i8, i8 } @gen9(i8 %key) {
227  %v0 = insertvalue { i8, i8, i8, i8 } undef, i8 %key, 0
228  %v1 = insertvalue { i8, i8, i8, i8 } %v0, i8 %key, 1
229  %v2 = insertvalue { i8, i8, i8, i8 } %v1, i8 %key, 2
230  %v3 = insertvalue { i8, i8, i8, i8 } %v2, i8 %key, 3
231  ret { i8, i8, i8, i8 } %v3
232}
233
234; CHECK-LABEL: _gen10
235; CHECK:  mov.16b         v1, v0
236; CHECK:  mov.16b         v2, v0
237; CHECK:  mov.16b         v3, v0
238; CHECK:  mov      w1, w0
239; CHECK:  mov      w2, w0
240; CHECK:  mov      w3, w0
241; CHECK:  ret
242define swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen10(double %keyd, i32 %keyi) {
243  %v0 = insertvalue { double, double, double, double, i32, i32, i32, i32 } undef, double %keyd, 0
244  %v1 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v0, double %keyd, 1
245  %v2 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v1, double %keyd, 2
246  %v3 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v2, double %keyd, 3
247  %v4 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v3, i32 %keyi, 4
248  %v5 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v4, i32 %keyi, 5
249  %v6 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v5, i32 %keyi, 6
250  %v7 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v6, i32 %keyi, 7
251  ret { double, double, double, double, i32, i32, i32, i32 } %v7
252}
253
254; CHECK-LABEL: _test11
255; CHECK:  bl      _gen11
256; CHECK:  fadd.4s v0, v0, v1
257; CHECK:  fadd.4s v0, v0, v2
258; CHECK:  fadd.4s v0, v0, v3
259define swiftcc <4 x float> @test11() {
260entry:
261  %call = call swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @gen11()
262
263  %v3 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 0
264  %v5 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 1
265  %v6 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 2
266  %v7 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 3
267
268  %add = fadd <4 x float> %v3, %v5
269  %add1 = fadd <4 x float> %add, %v6
270  %add2 = fadd <4 x float> %add1, %v7
271  ret <4 x float> %add2
272}
273
274declare swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @gen11()
275
276; CHECK-LABEL: _test12
277; CHECK:  fadd.4s v0, v0, v1
278; CHECK:  fadd.4s v0, v0, v2
279; CHECK:  mov.16b v1, v3
280define swiftcc { <4 x float>, float } @test12() #0 {
281entry:
282  %call = call swiftcc { <4 x float>, <4 x float>, <4 x float>, float } @gen12()
283
284  %v3 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 0
285  %v5 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 1
286  %v6 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 2
287  %v8 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 3
288
289  %add = fadd <4 x float> %v3, %v5
290  %add1 = fadd <4 x float> %add, %v6
291  %res.0 = insertvalue { <4 x float>, float } undef, <4 x float> %add1, 0
292  %res = insertvalue { <4 x float>, float } %res.0, float %v8, 1
293  ret { <4 x float>, float } %res
294}
295
296declare swiftcc { <4 x float>, <4 x float>, <4 x float>, float } @gen12()
297