1; RUN: llc -march=mipsel < %s | FileCheck %s
2
3
4; Check that function accesses vector return value from stack in cases when
5; vector can't be returned in registers. Also check that caller passes in
6; register $4 stack address where the vector should be placed.
7
8
9declare <8 x i32>    @i8(...)
10declare <4 x float>  @f4(...)
11declare <4 x double> @d4(...)
12
13define i32 @call_i8() {
14entry:
15  %call = call <8 x i32> (...)* @i8()
16  %v0 = extractelement <8 x i32> %call, i32 0
17  %v1 = extractelement <8 x i32> %call, i32 1
18  %v2 = extractelement <8 x i32> %call, i32 2
19  %v3 = extractelement <8 x i32> %call, i32 3
20  %v4 = extractelement <8 x i32> %call, i32 4
21  %v5 = extractelement <8 x i32> %call, i32 5
22  %v6 = extractelement <8 x i32> %call, i32 6
23  %v7 = extractelement <8 x i32> %call, i32 7
24  %add1 = add i32 %v0, %v1
25  %add2 = add i32 %v2, %v3
26  %add3 = add i32 %v4, %v5
27  %add4 = add i32 %v6, %v7
28  %add5 = add i32 %add1, %add2
29  %add6 = add i32 %add3, %add4
30  %add7 = add i32 %add5, %add6
31  ret i32 %add7
32
33; CHECK-LABEL:        call_i8:
34; CHECK:        call16(i8)
35; CHECK:        addiu   $4, $sp, 32
36; CHECK:        lw      $[[R0:[a-z0-9]+]], 60($sp)
37; CHECK:        lw      $[[R1:[a-z0-9]+]], 56($sp)
38; CHECK:        lw      $[[R2:[a-z0-9]+]], 52($sp)
39; CHECK:        lw      $[[R3:[a-z0-9]+]], 48($sp)
40; CHECK:        lw      $[[R4:[a-z0-9]+]], 44($sp)
41; CHECK:        lw      $[[R5:[a-z0-9]+]], 40($sp)
42; CHECK:        lw      $[[R6:[a-z0-9]+]], 36($sp)
43; CHECK:        lw      $[[R7:[a-z0-9]+]], 32($sp)
44}
45
46
47define float @call_f4() {
48entry:
49  %call = call <4 x float> (...)* @f4()
50  %v0 = extractelement <4 x float> %call, i32 0
51  %v1 = extractelement <4 x float> %call, i32 1
52  %v2 = extractelement <4 x float> %call, i32 2
53  %v3 = extractelement <4 x float> %call, i32 3
54  %add1 = fadd float %v0, %v1
55  %add2 = fadd float %v2, %v3
56  %add3 = fadd float %add1, %add2
57  ret float %add3
58
59; CHECK-LABEL:        call_f4:
60; CHECK:        call16(f4)
61; CHECK:        addiu   $4, $sp, 16
62; CHECK:        lwc1    $[[R0:[a-z0-9]+]], 28($sp)
63; CHECK:        lwc1    $[[R1:[a-z0-9]+]], 24($sp)
64; CHECK:        lwc1    $[[R3:[a-z0-9]+]], 20($sp)
65; CHECK:        lwc1    $[[R4:[a-z0-9]+]], 16($sp)
66}
67
68
69define double @call_d4() {
70entry:
71  %call = call <4 x double> (...)* @d4()
72  %v0 = extractelement <4 x double> %call, i32 0
73  %v1 = extractelement <4 x double> %call, i32 1
74  %v2 = extractelement <4 x double> %call, i32 2
75  %v3 = extractelement <4 x double> %call, i32 3
76  %add1 = fadd double %v0, %v1
77  %add2 = fadd double %v2, %v3
78  %add3 = fadd double %add1, %add2
79  ret double %add3
80
81; CHECK-LABEL:        call_d4:
82; CHECK:        call16(d4)
83; CHECK:        addiu   $4, $sp, 32
84; CHECK:        ldc1    $[[R0:[a-z0-9]+]], 56($sp)
85; CHECK:        ldc1    $[[R1:[a-z0-9]+]], 48($sp)
86; CHECK:        ldc1    $[[R3:[a-z0-9]+]], 40($sp)
87; CHECK:        ldc1    $[[R4:[a-z0-9]+]], 32($sp)
88}
89
90
91
92; Check that function accesses vector return value from registers in cases when
93; vector can be returned in registers
94
95
96declare <4 x i32>    @i4(...)
97declare <2 x float>  @f2(...)
98declare <2 x double> @d2(...)
99
100define i32 @call_i4() {
101entry:
102  %call = call <4 x i32> (...)* @i4()
103  %v0 = extractelement <4 x i32> %call, i32 0
104  %v1 = extractelement <4 x i32> %call, i32 1
105  %v2 = extractelement <4 x i32> %call, i32 2
106  %v3 = extractelement <4 x i32> %call, i32 3
107  %add1 = add i32 %v0, %v1
108  %add2 = add i32 %v2, %v3
109  %add3 = add i32 %add1, %add2
110  ret i32 %add3
111
112; CHECK-LABEL:        call_i4:
113; CHECK:        call16(i4)
114; CHECK-NOT:    lw
115; CHECK:        addu    $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]]
116; CHECK:        addu    $[[R5:[a-z0-9]+]], $[[R3:[a-z0-9]+]], $[[R4:[a-z0-9]+]]
117; CHECK:        addu    $[[R6:[a-z0-9]+]], $[[R5]], $[[R2]]
118}
119
120
121define float @call_f2() {
122entry:
123  %call = call <2 x float> (...)* @f2()
124  %v0 = extractelement <2 x float> %call, i32 0
125  %v1 = extractelement <2 x float> %call, i32 1
126  %add1 = fadd float %v0, %v1
127  ret float %add1
128
129; CHECK-LABEL:        call_f2:
130; CHECK:        call16(f2)
131; CHECK-NOT:    lwc1
132; CHECK:        add.s    $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]]
133}
134
135
136define double @call_d2() {
137entry:
138  %call = call <2 x double> (...)* @d2()
139  %v0 = extractelement <2 x double> %call, i32 0
140  %v1 = extractelement <2 x double> %call, i32 1
141  %add1 = fadd double %v0, %v1
142  ret double %add1
143
144; CHECK-LABEL:        call_d2:
145; CHECK:        call16(d2)
146; CHECK-NOT:    ldc1
147; CHECK:        add.d    $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]]
148}
149
150
151
152; Check that function returns vector on stack in cases when vector can't be
153; returned in registers. Also check that vector is placed on stack starting
154; from the address in register $4.
155
156
157define <8 x i32> @return_i8() {
158entry:
159  ret <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
160
161; CHECK-LABEL:        return_i8:
162; CHECK:        sw      $[[R0:[a-z0-9]+]], 28($4)
163; CHECK:        sw      $[[R1:[a-z0-9]+]], 24($4)
164; CHECK:        sw      $[[R2:[a-z0-9]+]], 20($4)
165; CHECK:        sw      $[[R3:[a-z0-9]+]], 16($4)
166; CHECK:        sw      $[[R4:[a-z0-9]+]], 12($4)
167; CHECK:        sw      $[[R5:[a-z0-9]+]], 8($4)
168; CHECK:        sw      $[[R6:[a-z0-9]+]], 4($4)
169; CHECK:        sw      $[[R7:[a-z0-9]+]], 0($4)
170}
171
172
173define <4 x float> @return_f4(float %a, float %b, float %c, float %d) {
174entry:
175  %vecins1 = insertelement <4 x float> undef,    float %a, i32 0
176  %vecins2 = insertelement <4 x float> %vecins1, float %b, i32 1
177  %vecins3 = insertelement <4 x float> %vecins2, float %c, i32 2
178  %vecins4 = insertelement <4 x float> %vecins3, float %d, i32 3
179  ret <4 x float> %vecins4
180
181; CHECK-LABEL:        return_f4:
182; CHECK-DAG:    lwc1    $[[R0:[a-z0-9]+]], 16($sp)
183; CHECK-DAG:    swc1    $[[R0]], 12($4)
184; CHECK-DAG:    sw      $7, 8($4)
185; CHECK-DAG:    sw      $6, 4($4)
186; CHECK-DAG:    sw      $5, 0($4)
187}
188
189
190define <4 x double> @return_d4(double %a, double %b, double %c, double %d) {
191entry:
192  %vecins1 = insertelement <4 x double> undef,    double %a, i32 0
193  %vecins2 = insertelement <4 x double> %vecins1, double %b, i32 1
194  %vecins3 = insertelement <4 x double> %vecins2, double %c, i32 2
195  %vecins4 = insertelement <4 x double> %vecins3, double %d, i32 3
196  ret <4 x double> %vecins4
197
198; CHECK-LABEL:            return_d4:
199; CHECK-DAG:        sdc1    $[[R0:[a-z0-9]+]], 24($4)
200; CHECK-DAG:        sdc1    $[[R1:[a-z0-9]+]], 16($4)
201; CHECK-DAG:        sdc1    $[[R2:[a-z0-9]+]], 8($4)
202; CHECK-DAG:        sdc1    $[[R3:[a-z0-9]+]], 0($4)
203}
204
205
206
207; Check that function returns vector in registers in cases when vector can be
208; returned in registers.
209
210
211define <4 x i32> @return_i4() {
212entry:
213  ret <4 x i32> <i32 0, i32 1, i32 2, i32 3>
214
215; CHECK-LABEL:        return_i4:
216; CHECK:        addiu   $2, $zero, 0
217; CHECK:        addiu   $3, $zero, 1
218; CHECK:        addiu   $4, $zero, 2
219; CHECK:        addiu   $5, $zero, 3
220}
221
222
223define <2 x float> @return_f2(float %a, float %b) {
224entry:
225  %vecins1 = insertelement <2 x float> undef,    float %a, i32 0
226  %vecins2 = insertelement <2 x float> %vecins1, float %b, i32 1
227  ret <2 x float> %vecins2
228
229; CHECK-LABEL:        return_f2:
230; CHECK:        mov.s   $f0, $f12
231; CHECK:        mov.s   $f2, $f14
232}
233
234
235define <2 x double> @return_d2(double %a, double %b) {
236entry:
237  %vecins1 = insertelement <2 x double> undef,    double %a, i32 0
238  %vecins2 = insertelement <2 x double> %vecins1, double %b, i32 1
239  ret <2 x double> %vecins2
240
241; CHECK-LABEL:        return_d2:
242; CHECK:        mov.d   $f0, $f12
243; CHECK:        mov.d   $f2, $f14
244}
245