f1e0b7c28620416e7efce56ce4d7dc096ee35ace
[oota-llvm.git] / test / CodeGen / Mips / msa / basic_operations.ll
1 ; RUN: llc -march=mips -mattr=+msa,+fp64 < %s | FileCheck -check-prefix=ALL -check-prefix=MIPS32-BE %s
2 ; RUN: llc -march=mipsel -mattr=+msa,+fp64 < %s | FileCheck -check-prefix=ALL -check-prefix=MIPS32-LE %s
3
4 @v4i8 = global <4 x i8> <i8 0, i8 0, i8 0, i8 0>
5 @v16i8 = global <16 x i8> <i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>
6 @v8i16 = global <8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>
7 @v4i32 = global <4 x i32> <i32 0, i32 0, i32 0, i32 0>
8 @v2i64 = global <2 x i64> <i64 0, i64 0>
9 @i32 = global i32 0
10 @i64 = global i64 0
11
12 define void @const_v16i8() nounwind {
13   ; ALL-LABEL: const_v16i8:
14
15   store volatile <16 x i8> <i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, <16 x i8>*@v16i8
16   ; ALL: ldi.b [[R1:\$w[0-9]+]], 0
17
18   store volatile <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <16 x i8>*@v16i8
19   ; ALL: ldi.b [[R1:\$w[0-9]+]], 1
20
21   store volatile <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 31>, <16 x i8>*@v16i8
22   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
23   ; ALL: ld.b  [[R1:\$w[0-9]+]], 0([[G_PTR]])
24
25   store volatile <16 x i8> <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6>, <16 x i8>*@v16i8
26   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
27   ; ALL: ld.b  [[R1:\$w[0-9]+]], 0([[G_PTR]])
28
29   store volatile <16 x i8> <i8 1, i8 0, i8 1, i8 0, i8 1, i8 0, i8 1, i8 0, i8 1, i8 0, i8 1, i8 0, i8 1, i8 0, i8 1, i8 0>, <16 x i8>*@v16i8
30   ; MIPS32-BE: ldi.h [[R1:\$w[0-9]+]], 256
31   ; MIPS32-LE: ldi.h [[R1:\$w[0-9]+]], 1
32
33   store volatile <16 x i8> <i8 1, i8 2, i8 3, i8 4, i8 1, i8 2, i8 3, i8 4, i8 1, i8 2, i8 3, i8 4, i8 1, i8 2, i8 3, i8 4>, <16 x i8>*@v16i8
34   ; MIPS32-BE-DAG: lui [[R2:\$[0-9]+]], 258
35   ; MIPS32-LE-DAG: lui [[R2:\$[0-9]+]], 1027
36   ; MIPS32-BE-DAG: ori [[R2]], [[R2]], 772
37   ; MIPS32-LE-DAG: ori [[R2]], [[R2]], 513
38   ; ALL-DAG: fill.w [[R1:\$w[0-9]+]], [[R2]]
39
40   store volatile <16 x i8> <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>, <16 x i8>*@v16i8
41   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
42   ; ALL: ld.b  [[R1:\$w[0-9]+]], 0([[G_PTR]])
43
44   ret void
45 }
46
47 define void @const_v8i16() nounwind {
48   ; ALL-LABEL: const_v8i16:
49
50   store volatile <8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16>*@v8i16
51   ; ALL: ldi.b [[R1:\$w[0-9]+]], 0
52
53   store volatile <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, <8 x i16>*@v8i16
54   ; ALL: ldi.h [[R1:\$w[0-9]+]], 1
55
56   store volatile <8 x i16> <i16 1, i16 1, i16 1, i16 2, i16 1, i16 1, i16 1, i16 31>, <8 x i16>*@v8i16
57   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
58   ; ALL: ld.h  [[R1:\$w[0-9]+]], 0([[G_PTR]])
59
60   store volatile <8 x i16> <i16 1028, i16 1028, i16 1028, i16 1028, i16 1028, i16 1028, i16 1028, i16 1028>, <8 x i16>*@v8i16
61   ; ALL: ldi.b [[R1:\$w[0-9]+]], 4
62
63   store volatile <8 x i16> <i16 1, i16 2, i16 1, i16 2, i16 1, i16 2, i16 1, i16 2>, <8 x i16>*@v8i16
64   ; MIPS32-BE-DAG: lui [[R2:\$[0-9]+]], 1
65   ; MIPS32-LE-DAG: lui [[R2:\$[0-9]+]], 2
66   ; MIPS32-BE-DAG: ori [[R2]], [[R2]], 2
67   ; MIPS32-LE-DAG: ori [[R2]], [[R2]], 1
68   ; ALL-DAG: fill.w [[R1:\$w[0-9]+]], [[R2]]
69
70   store volatile <8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 1, i16 2, i16 3, i16 4>, <8 x i16>*@v8i16
71   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
72   ; ALL: ld.h  [[R1:\$w[0-9]+]], 0([[G_PTR]])
73
74   ret void
75 }
76
77 define void @const_v4i32() nounwind {
78   ; ALL-LABEL: const_v4i32:
79
80   store volatile <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32>*@v4i32
81   ; ALL: ldi.b [[R1:\$w[0-9]+]], 0
82
83   store volatile <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32>*@v4i32
84   ; ALL: ldi.w [[R1:\$w[0-9]+]], 1
85
86   store volatile <4 x i32> <i32 1, i32 1, i32 1, i32 31>, <4 x i32>*@v4i32
87   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
88   ; ALL: ld.w  [[R1:\$w[0-9]+]], 0([[G_PTR]])
89
90   store volatile <4 x i32> <i32 16843009, i32 16843009, i32 16843009, i32 16843009>, <4 x i32>*@v4i32
91   ; ALL: ldi.b [[R1:\$w[0-9]+]], 1
92
93   store volatile <4 x i32> <i32 65537, i32 65537, i32 65537, i32 65537>, <4 x i32>*@v4i32
94   ; ALL: ldi.h [[R1:\$w[0-9]+]], 1
95
96   store volatile <4 x i32> <i32 1, i32 2, i32 1, i32 2>, <4 x i32>*@v4i32
97   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
98   ; ALL: ld.w  [[R1:\$w[0-9]+]], 0([[G_PTR]])
99
100   store volatile <4 x i32> <i32 3, i32 4, i32 5, i32 6>, <4 x i32>*@v4i32
101   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
102   ; ALL: ld.w  [[R1:\$w[0-9]+]], 0([[G_PTR]])
103
104   ret void
105 }
106
107 define void @const_v2i64() nounwind {
108   ; ALL-LABEL: const_v2i64:
109
110   store volatile <2 x i64> <i64 0, i64 0>, <2 x i64>*@v2i64
111   ; ALL: ldi.b [[R1:\$w[0-9]+]], 0
112
113   store volatile <2 x i64> <i64 72340172838076673, i64 72340172838076673>, <2 x i64>*@v2i64
114   ; ALL: ldi.b [[R1:\$w[0-9]+]], 1
115
116   store volatile <2 x i64> <i64 281479271743489, i64 281479271743489>, <2 x i64>*@v2i64
117   ; ALL: ldi.h [[R1:\$w[0-9]+]], 1
118
119   store volatile <2 x i64> <i64 4294967297, i64 4294967297>, <2 x i64>*@v2i64
120   ; ALL: ldi.w [[R1:\$w[0-9]+]], 1
121
122   store volatile <2 x i64> <i64 1, i64 1>, <2 x i64>*@v2i64
123   ; ALL: ldi.d [[R1:\$w[0-9]+]], 1
124
125   store volatile <2 x i64> <i64 1, i64 31>, <2 x i64>*@v2i64
126   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
127   ; ALL: ld.w  [[R1:\$w[0-9]+]], 0([[G_PTR]])
128
129   store volatile <2 x i64> <i64 3, i64 4>, <2 x i64>*@v2i64
130   ; ALL: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($
131   ; ALL: ld.w  [[R1:\$w[0-9]+]], 0([[G_PTR]])
132
133   ret void
134 }
135
136 define void @nonconst_v16i8(i8 signext %a, i8 signext %b, i8 signext %c, i8 signext %d, i8 signext %e, i8 signext %f, i8 signext %g, i8 signext %h) nounwind {
137   ; ALL-LABEL: nonconst_v16i8:
138
139   %1 = insertelement <16 x i8> undef, i8 %a, i32 0
140   %2 = insertelement <16 x i8> %1, i8 %b, i32 1
141   %3 = insertelement <16 x i8> %2, i8 %c, i32 2
142   %4 = insertelement <16 x i8> %3, i8 %d, i32 3
143   %5 = insertelement <16 x i8> %4, i8 %e, i32 4
144   %6 = insertelement <16 x i8> %5, i8 %f, i32 5
145   %7 = insertelement <16 x i8> %6, i8 %g, i32 6
146   %8 = insertelement <16 x i8> %7, i8 %h, i32 7
147   %9 = insertelement <16 x i8> %8, i8 %h, i32 8
148   %10 = insertelement <16 x i8> %9, i8 %h, i32 9
149   %11 = insertelement <16 x i8> %10, i8 %h, i32 10
150   %12 = insertelement <16 x i8> %11, i8 %h, i32 11
151   %13 = insertelement <16 x i8> %12, i8 %h, i32 12
152   %14 = insertelement <16 x i8> %13, i8 %h, i32 13
153   %15 = insertelement <16 x i8> %14, i8 %h, i32 14
154   %16 = insertelement <16 x i8> %15, i8 %h, i32 15
155   ; ALL-DAG: insert.b [[R1:\$w[0-9]+]][0], $4
156   ; ALL-DAG: insert.b [[R1]][1], $5
157   ; ALL-DAG: insert.b [[R1]][2], $6
158   ; ALL-DAG: insert.b [[R1]][3], $7
159   ; ALL-DAG: lw [[R2:\$[0-9]+]], 16($sp)
160   ; ALL-DAG: insert.b [[R1]][4], [[R2]]
161   ; ALL-DAG: lw [[R3:\$[0-9]+]], 20($sp)
162   ; ALL-DAG: insert.b [[R1]][5], [[R3]]
163   ; ALL-DAG: lw [[R4:\$[0-9]+]], 24($sp)
164   ; ALL-DAG: insert.b [[R1]][6], [[R4]]
165   ; ALL-DAG: lw [[R5:\$[0-9]+]], 28($sp)
166   ; ALL-DAG: insert.b [[R1]][7], [[R5]]
167   ; ALL-DAG: insert.b [[R1]][8], [[R5]]
168   ; ALL-DAG: insert.b [[R1]][9], [[R5]]
169   ; ALL-DAG: insert.b [[R1]][10], [[R5]]
170   ; ALL-DAG: insert.b [[R1]][11], [[R5]]
171   ; ALL-DAG: insert.b [[R1]][12], [[R5]]
172   ; ALL-DAG: insert.b [[R1]][13], [[R5]]
173   ; ALL-DAG: insert.b [[R1]][14], [[R5]]
174   ; ALL-DAG: insert.b [[R1]][15], [[R5]]
175
176   store volatile <16 x i8> %16, <16 x i8>*@v16i8
177
178   ret void
179 }
180
181 define void @nonconst_v8i16(i16 signext %a, i16 signext %b, i16 signext %c, i16 signext %d, i16 signext %e, i16 signext %f, i16 signext %g, i16 signext %h) nounwind {
182   ; ALL-LABEL: nonconst_v8i16:
183
184   %1 = insertelement <8 x i16> undef, i16 %a, i32 0
185   %2 = insertelement <8 x i16> %1, i16 %b, i32 1
186   %3 = insertelement <8 x i16> %2, i16 %c, i32 2
187   %4 = insertelement <8 x i16> %3, i16 %d, i32 3
188   %5 = insertelement <8 x i16> %4, i16 %e, i32 4
189   %6 = insertelement <8 x i16> %5, i16 %f, i32 5
190   %7 = insertelement <8 x i16> %6, i16 %g, i32 6
191   %8 = insertelement <8 x i16> %7, i16 %h, i32 7
192   ; ALL-DAG: insert.h [[R1:\$w[0-9]+]][0], $4
193   ; ALL-DAG: insert.h [[R1]][1], $5
194   ; ALL-DAG: insert.h [[R1]][2], $6
195   ; ALL-DAG: insert.h [[R1]][3], $7
196   ; ALL-DAG: lw [[R2:\$[0-9]+]], 16($sp)
197   ; ALL-DAG: insert.h [[R1]][4], [[R2]]
198   ; ALL-DAG: lw [[R2:\$[0-9]+]], 20($sp)
199   ; ALL-DAG: insert.h [[R1]][5], [[R2]]
200   ; ALL-DAG: lw [[R2:\$[0-9]+]], 24($sp)
201   ; ALL-DAG: insert.h [[R1]][6], [[R2]]
202   ; ALL-DAG: lw [[R2:\$[0-9]+]], 28($sp)
203   ; ALL-DAG: insert.h [[R1]][7], [[R2]]
204
205   store volatile <8 x i16> %8, <8 x i16>*@v8i16
206
207   ret void
208 }
209
210 define void @nonconst_v4i32(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d) nounwind {
211   ; ALL-LABEL: nonconst_v4i32:
212
213   %1 = insertelement <4 x i32> undef, i32 %a, i32 0
214   %2 = insertelement <4 x i32> %1, i32 %b, i32 1
215   %3 = insertelement <4 x i32> %2, i32 %c, i32 2
216   %4 = insertelement <4 x i32> %3, i32 %d, i32 3
217   ; ALL: insert.w [[R1:\$w[0-9]+]][0], $4
218   ; ALL: insert.w [[R1]][1], $5
219   ; ALL: insert.w [[R1]][2], $6
220   ; ALL: insert.w [[R1]][3], $7
221
222   store volatile <4 x i32> %4, <4 x i32>*@v4i32
223
224   ret void
225 }
226
227 define void @nonconst_v2i64(i64 signext %a, i64 signext %b) nounwind {
228   ; ALL-LABEL: nonconst_v2i64:
229
230   %1 = insertelement <2 x i64> undef, i64 %a, i32 0
231   %2 = insertelement <2 x i64> %1, i64 %b, i32 1
232   ; ALL: insert.w [[R1:\$w[0-9]+]][0], $4
233   ; ALL: insert.w [[R1]][1], $5
234   ; ALL: insert.w [[R1]][2], $6
235   ; ALL: insert.w [[R1]][3], $7
236
237   store volatile <2 x i64> %2, <2 x i64>*@v2i64
238
239   ret void
240 }
241
242 define i32 @extract_sext_v16i8() nounwind {
243   ; ALL-LABEL: extract_sext_v16i8:
244
245   %1 = load <16 x i8>, <16 x i8>* @v16i8
246   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]],
247
248   %2 = add <16 x i8> %1, %1
249   ; ALL-DAG: addv.b [[R2:\$w[0-9]+]], [[R1]], [[R1]]
250
251   %3 = extractelement <16 x i8> %2, i32 1
252   %4 = sext i8 %3 to i32
253   ; ALL-DAG: copy_s.b [[R3:\$[0-9]+]], [[R1]][1]
254   ; ALL-NOT: sll
255   ; ALL-NOT: sra
256
257   ret i32 %4
258 }
259
260 define i32 @extract_sext_v8i16() nounwind {
261   ; ALL-LABEL: extract_sext_v8i16:
262
263   %1 = load <8 x i16>, <8 x i16>* @v8i16
264   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]],
265
266   %2 = add <8 x i16> %1, %1
267   ; ALL-DAG: addv.h [[R2:\$w[0-9]+]], [[R1]], [[R1]]
268
269   %3 = extractelement <8 x i16> %2, i32 1
270   %4 = sext i16 %3 to i32
271   ; ALL-DAG: copy_s.h [[R3:\$[0-9]+]], [[R1]][1]
272   ; ALL-NOT: sll
273   ; ALL-NOT: sra
274
275   ret i32 %4
276 }
277
278 define i32 @extract_sext_v4i32() nounwind {
279   ; ALL-LABEL: extract_sext_v4i32:
280
281   %1 = load <4 x i32>, <4 x i32>* @v4i32
282   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
283
284   %2 = add <4 x i32> %1, %1
285   ; ALL-DAG: addv.w [[R2:\$w[0-9]+]], [[R1]], [[R1]]
286
287   %3 = extractelement <4 x i32> %2, i32 1
288   ; ALL-DAG: copy_s.w [[R3:\$[0-9]+]], [[R1]][1]
289
290   ret i32 %3
291 }
292
293 define i64 @extract_sext_v2i64() nounwind {
294   ; ALL-LABEL: extract_sext_v2i64:
295
296   %1 = load <2 x i64>, <2 x i64>* @v2i64
297   ; ALL-DAG: ld.d [[R1:\$w[0-9]+]],
298
299   %2 = add <2 x i64> %1, %1
300   ; ALL-DAG: addv.d [[R2:\$w[0-9]+]], [[R1]], [[R1]]
301
302   %3 = extractelement <2 x i64> %2, i32 1
303   ; ALL-DAG: copy_s.w [[R3:\$[0-9]+]], [[R1]][2]
304   ; ALL-DAG: copy_s.w [[R4:\$[0-9]+]], [[R1]][3]
305   ; ALL-NOT: sll
306   ; ALL-NOT: sra
307
308   ret i64 %3
309 }
310
311 define i32 @extract_zext_v16i8() nounwind {
312   ; ALL-LABEL: extract_zext_v16i8:
313
314   %1 = load <16 x i8>, <16 x i8>* @v16i8
315   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]],
316
317   %2 = add <16 x i8> %1, %1
318   ; ALL-DAG: addv.b [[R2:\$w[0-9]+]], [[R1]], [[R1]]
319
320   %3 = extractelement <16 x i8> %2, i32 1
321   %4 = zext i8 %3 to i32
322   ; ALL-DAG: copy_u.b [[R3:\$[0-9]+]], [[R1]][1]
323   ; ALL-NOT: andi
324
325   ret i32 %4
326 }
327
328 define i32 @extract_zext_v8i16() nounwind {
329   ; ALL-LABEL: extract_zext_v8i16:
330
331   %1 = load <8 x i16>, <8 x i16>* @v8i16
332   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]],
333
334   %2 = add <8 x i16> %1, %1
335   ; ALL-DAG: addv.h [[R2:\$w[0-9]+]], [[R1]], [[R1]]
336
337   %3 = extractelement <8 x i16> %2, i32 1
338   %4 = zext i16 %3 to i32
339   ; ALL-DAG: copy_u.h [[R3:\$[0-9]+]], [[R1]][1]
340   ; ALL-NOT: andi
341
342   ret i32 %4
343 }
344
345 define i32 @extract_zext_v4i32() nounwind {
346   ; ALL-LABEL: extract_zext_v4i32:
347
348   %1 = load <4 x i32>, <4 x i32>* @v4i32
349   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
350
351   %2 = add <4 x i32> %1, %1
352   ; ALL-DAG: addv.w [[R2:\$w[0-9]+]], [[R1]], [[R1]]
353
354   %3 = extractelement <4 x i32> %2, i32 1
355   ; ALL-DAG: copy_{{[su]}}.w [[R3:\$[0-9]+]], [[R1]][1]
356
357   ret i32 %3
358 }
359
360 define i64 @extract_zext_v2i64() nounwind {
361   ; ALL-LABEL: extract_zext_v2i64:
362
363   %1 = load <2 x i64>, <2 x i64>* @v2i64
364   ; ALL-DAG: ld.d [[R1:\$w[0-9]+]],
365
366   %2 = add <2 x i64> %1, %1
367   ; ALL-DAG: addv.d [[R2:\$w[0-9]+]], [[R1]], [[R1]]
368
369   %3 = extractelement <2 x i64> %2, i32 1
370   ; ALL-DAG: copy_{{[su]}}.w [[R3:\$[0-9]+]], [[R1]][2]
371   ; ALL-DAG: copy_{{[su]}}.w [[R4:\$[0-9]+]], [[R1]][3]
372   ; ALL-NOT: andi
373
374   ret i64 %3
375 }
376
377 define i32 @extract_sext_v16i8_vidx() nounwind {
378   ; ALL-LABEL: extract_sext_v16i8_vidx:
379
380   %1 = load <16 x i8>, <16 x i8>* @v16i8
381   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v16i8)(
382   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]], 0([[PTR_V]])
383
384   %2 = add <16 x i8> %1, %1
385   ; ALL-DAG: addv.b [[R2:\$w[0-9]+]], [[R1]], [[R1]]
386
387   %3 = load i32, i32* @i32
388   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
389   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
390
391   %4 = extractelement <16 x i8> %2, i32 %3
392   %5 = sext i8 %4 to i32
393   ; ALL-DAG: splat.b $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
394   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
395   ; ALL-DAG: sra [[R6:\$[0-9]+]], [[R5]], 24
396
397   ret i32 %5
398 }
399
400 define i32 @extract_sext_v8i16_vidx() nounwind {
401   ; ALL-LABEL: extract_sext_v8i16_vidx:
402
403   %1 = load <8 x i16>, <8 x i16>* @v8i16
404   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v8i16)(
405   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]], 0([[PTR_V]])
406
407   %2 = add <8 x i16> %1, %1
408   ; ALL-DAG: addv.h [[R2:\$w[0-9]+]], [[R1]], [[R1]]
409
410   %3 = load i32, i32* @i32
411   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
412   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
413
414   %4 = extractelement <8 x i16> %2, i32 %3
415   %5 = sext i16 %4 to i32
416   ; ALL-DAG: splat.h $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
417   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
418   ; ALL-DAG: sra [[R6:\$[0-9]+]], [[R5]], 16
419
420   ret i32 %5
421 }
422
423 define i32 @extract_sext_v4i32_vidx() nounwind {
424   ; ALL-LABEL: extract_sext_v4i32_vidx:
425
426   %1 = load <4 x i32>, <4 x i32>* @v4i32
427   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v4i32)(
428   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]], 0([[PTR_V]])
429
430   %2 = add <4 x i32> %1, %1
431   ; ALL-DAG: addv.w [[R2:\$w[0-9]+]], [[R1]], [[R1]]
432
433   %3 = load i32, i32* @i32
434   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
435   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
436
437   %4 = extractelement <4 x i32> %2, i32 %3
438   ; ALL-DAG: splat.w $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
439   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
440   ; ALL-NOT: sra
441
442   ret i32 %4
443 }
444
445 define i64 @extract_sext_v2i64_vidx() nounwind {
446   ; ALL-LABEL: extract_sext_v2i64_vidx:
447
448   %1 = load <2 x i64>, <2 x i64>* @v2i64
449   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v2i64)(
450   ; ALL-DAG: ld.d [[R1:\$w[0-9]+]], 0([[PTR_V]])
451
452   %2 = add <2 x i64> %1, %1
453   ; ALL-DAG: addv.d [[R2:\$w[0-9]+]], [[R1]], [[R1]]
454
455   %3 = load i32, i32* @i32
456   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
457   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
458
459   %4 = extractelement <2 x i64> %2, i32 %3
460   ; ALL-DAG: splat.w $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
461   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
462   ; ALL-DAG: splat.w $w[[R4:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
463   ; ALL-DAG: mfc1 [[R6:\$[0-9]+]], $f[[R4]]
464   ; ALL-NOT: sra
465
466   ret i64 %4
467 }
468
469 define i32 @extract_zext_v16i8_vidx() nounwind {
470   ; ALL-LABEL: extract_zext_v16i8_vidx:
471
472   %1 = load <16 x i8>, <16 x i8>* @v16i8
473   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v16i8)(
474   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]], 0([[PTR_V]])
475
476   %2 = add <16 x i8> %1, %1
477   ; ALL-DAG: addv.b [[R2:\$w[0-9]+]], [[R1]], [[R1]]
478
479   %3 = load i32, i32* @i32
480   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
481   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
482
483   %4 = extractelement <16 x i8> %2, i32 %3
484   %5 = zext i8 %4 to i32
485   ; ALL-DAG: splat.b $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
486   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
487   ; ALL-DAG: srl [[R6:\$[0-9]+]], [[R5]], 24
488
489   ret i32 %5
490 }
491
492 define i32 @extract_zext_v8i16_vidx() nounwind {
493   ; ALL-LABEL: extract_zext_v8i16_vidx:
494
495   %1 = load <8 x i16>, <8 x i16>* @v8i16
496   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v8i16)(
497   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]], 0([[PTR_V]])
498
499   %2 = add <8 x i16> %1, %1
500   ; ALL-DAG: addv.h [[R2:\$w[0-9]+]], [[R1]], [[R1]]
501
502   %3 = load i32, i32* @i32
503   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
504   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
505
506   %4 = extractelement <8 x i16> %2, i32 %3
507   %5 = zext i16 %4 to i32
508   ; ALL-DAG: splat.h $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
509   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
510   ; ALL-DAG: srl [[R6:\$[0-9]+]], [[R5]], 16
511
512   ret i32 %5
513 }
514
515 define i32 @extract_zext_v4i32_vidx() nounwind {
516   ; ALL-LABEL: extract_zext_v4i32_vidx:
517
518   %1 = load <4 x i32>, <4 x i32>* @v4i32
519   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v4i32)(
520   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]], 0([[PTR_V]])
521
522   %2 = add <4 x i32> %1, %1
523   ; ALL-DAG: addv.w [[R2:\$w[0-9]+]], [[R1]], [[R1]]
524
525   %3 = load i32, i32* @i32
526   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
527   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
528
529   %4 = extractelement <4 x i32> %2, i32 %3
530   ; ALL-DAG: splat.w $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
531   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
532   ; ALL-NOT: srl
533
534   ret i32 %4
535 }
536
537 define i64 @extract_zext_v2i64_vidx() nounwind {
538   ; ALL-LABEL: extract_zext_v2i64_vidx:
539
540   %1 = load <2 x i64>, <2 x i64>* @v2i64
541   ; ALL-DAG: lw [[PTR_V:\$[0-9]+]], %got(v2i64)(
542   ; ALL-DAG: ld.d [[R1:\$w[0-9]+]], 0([[PTR_V]])
543
544   %2 = add <2 x i64> %1, %1
545   ; ALL-DAG: addv.d [[R2:\$w[0-9]+]], [[R1]], [[R1]]
546
547   %3 = load i32, i32* @i32
548   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
549   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
550
551   %4 = extractelement <2 x i64> %2, i32 %3
552   ; ALL-DAG: splat.w $w[[R3:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
553   ; ALL-DAG: mfc1 [[R5:\$[0-9]+]], $f[[R3]]
554   ; ALL-DAG: splat.w $w[[R4:[0-9]+]], [[R1]]{{\[}}[[IDX]]]
555   ; ALL-DAG: mfc1 [[R6:\$[0-9]+]], $f[[R4]]
556   ; ALL-NOT: srl
557
558   ret i64 %4
559 }
560
561 define void @insert_v16i8(i32 signext %a) nounwind {
562   ; ALL-LABEL: insert_v16i8:
563
564   %1 = load <16 x i8>, <16 x i8>* @v16i8
565   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]],
566
567   %a2 = trunc i32 %a to i8
568   %a3 = sext i8 %a2 to i32
569   %a4 = trunc i32 %a3 to i8
570   ; ALL-NOT: andi
571   ; ALL-NOT: sra
572
573   %2 = insertelement <16 x i8> %1, i8 %a4, i32 1
574   ; ALL-DAG: insert.b [[R1]][1], $4
575
576   store <16 x i8> %2, <16 x i8>* @v16i8
577   ; ALL-DAG: st.b [[R1]]
578
579   ret void
580 }
581
582 define void @insert_v8i16(i32 signext %a) nounwind {
583   ; ALL-LABEL: insert_v8i16:
584
585   %1 = load <8 x i16>, <8 x i16>* @v8i16
586   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]],
587
588   %a2 = trunc i32 %a to i16
589   %a3 = sext i16 %a2 to i32
590   %a4 = trunc i32 %a3 to i16
591   ; ALL-NOT: andi
592   ; ALL-NOT: sra
593
594   %2 = insertelement <8 x i16> %1, i16 %a4, i32 1
595   ; ALL-DAG: insert.h [[R1]][1], $4
596
597   store <8 x i16> %2, <8 x i16>* @v8i16
598   ; ALL-DAG: st.h [[R1]]
599
600   ret void
601 }
602
603 define void @insert_v4i32(i32 signext %a) nounwind {
604   ; ALL-LABEL: insert_v4i32:
605
606   %1 = load <4 x i32>, <4 x i32>* @v4i32
607   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
608
609   ; ALL-NOT: andi
610   ; ALL-NOT: sra
611
612   %2 = insertelement <4 x i32> %1, i32 %a, i32 1
613   ; ALL-DAG: insert.w [[R1]][1], $4
614
615   store <4 x i32> %2, <4 x i32>* @v4i32
616   ; ALL-DAG: st.w [[R1]]
617
618   ret void
619 }
620
621 define void @insert_v2i64(i64 signext %a) nounwind {
622   ; ALL-LABEL: insert_v2i64:
623
624   %1 = load <2 x i64>, <2 x i64>* @v2i64
625   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
626
627   ; ALL-NOT: andi
628   ; ALL-NOT: sra
629
630   %2 = insertelement <2 x i64> %1, i64 %a, i32 1
631   ; ALL-DAG: insert.w [[R1]][2], $4
632   ; ALL-DAG: insert.w [[R1]][3], $5
633
634   store <2 x i64> %2, <2 x i64>* @v2i64
635   ; ALL-DAG: st.w [[R1]]
636
637   ret void
638 }
639
640 define void @insert_v16i8_vidx(i32 signext %a) nounwind {
641   ; ALL-LABEL: insert_v16i8_vidx:
642
643   %1 = load <16 x i8>, <16 x i8>* @v16i8
644   ; ALL-DAG: ld.b [[R1:\$w[0-9]+]],
645
646   %2 = load i32, i32* @i32
647   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
648   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
649
650   %a2 = trunc i32 %a to i8
651   %a3 = sext i8 %a2 to i32
652   %a4 = trunc i32 %a3 to i8
653   ; ALL-NOT: andi
654   ; ALL-NOT: sra
655
656   %3 = insertelement <16 x i8> %1, i8 %a4, i32 %2
657   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[IDX]]]
658   ; ALL-DAG: insert.b [[R1]][0], $4
659   ; ALL-DAG: neg [[NIDX:\$[0-9]+]], [[IDX]]
660   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[NIDX]]]
661
662   store <16 x i8> %3, <16 x i8>* @v16i8
663   ; ALL-DAG: st.b [[R1]]
664
665   ret void
666 }
667
668 define void @insert_v8i16_vidx(i32 %a) nounwind {
669   ; ALL-LABEL: insert_v8i16_vidx:
670
671   %1 = load <8 x i16>, <8 x i16>* @v8i16
672   ; ALL-DAG: ld.h [[R1:\$w[0-9]+]],
673
674   %2 = load i32, i32* @i32
675   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
676   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
677
678   %a2 = trunc i32 %a to i16
679   %a3 = sext i16 %a2 to i32
680   %a4 = trunc i32 %a3 to i16
681   ; ALL-NOT: andi
682   ; ALL-NOT: sra
683
684   %3 = insertelement <8 x i16> %1, i16 %a4, i32 %2
685   ; ALL-DAG: sll [[BIDX:\$[0-9]+]], [[IDX]], 1
686   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[BIDX]]]
687   ; ALL-DAG: insert.h [[R1]][0], $4
688   ; ALL-DAG: neg [[NIDX:\$[0-9]+]], [[BIDX]]
689   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[NIDX]]]
690
691   store <8 x i16> %3, <8 x i16>* @v8i16
692   ; ALL-DAG: st.h [[R1]]
693
694   ret void
695 }
696
697 define void @insert_v4i32_vidx(i32 signext %a) nounwind {
698   ; ALL-LABEL: insert_v4i32_vidx:
699
700   %1 = load <4 x i32>, <4 x i32>* @v4i32
701   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
702
703   %2 = load i32, i32* @i32
704   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
705   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
706
707   ; ALL-NOT: andi
708   ; ALL-NOT: sra
709
710   %3 = insertelement <4 x i32> %1, i32 %a, i32 %2
711   ; ALL-DAG: sll [[BIDX:\$[0-9]+]], [[IDX]], 2
712   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[BIDX]]]
713   ; ALL-DAG: insert.w [[R1]][0], $4
714   ; ALL-DAG: neg [[NIDX:\$[0-9]+]], [[BIDX]]
715   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[NIDX]]]
716
717   store <4 x i32> %3, <4 x i32>* @v4i32
718   ; ALL-DAG: st.w [[R1]]
719
720   ret void
721 }
722
723 define void @insert_v2i64_vidx(i64 signext %a) nounwind {
724   ; ALL-LABEL: insert_v2i64_vidx:
725
726   %1 = load <2 x i64>, <2 x i64>* @v2i64
727   ; ALL-DAG: ld.w [[R1:\$w[0-9]+]],
728
729   %2 = load i32, i32* @i32
730   ; ALL-DAG: lw [[PTR_I:\$[0-9]+]], %got(i32)(
731   ; ALL-DAG: lw [[IDX:\$[0-9]+]], 0([[PTR_I]])
732
733   ; ALL-NOT: andi
734   ; ALL-NOT: sra
735
736   %3 = insertelement <2 x i64> %1, i64 %a, i32 %2
737   ; TODO: This code could be a lot better but it works. The legalizer splits
738   ; 64-bit inserts into two 32-bit inserts because there is no i64 type on
739   ; MIPS32. The obvious optimisation is to perform both insert.w's at once while
740   ; the vector is rotated.
741   ; ALL-DAG: sll [[BIDX:\$[0-9]+]], [[IDX]], 2
742   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[BIDX]]]
743   ; ALL-DAG: insert.w [[R1]][0], $4
744   ; ALL-DAG: neg [[NIDX:\$[0-9]+]], [[BIDX]]
745   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[NIDX]]]
746   ; ALL-DAG: addiu [[IDX2:\$[0-9]+]], [[IDX]], 1
747   ; ALL-DAG: sll [[BIDX:\$[0-9]+]], [[IDX2]], 2
748   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[BIDX]]]
749   ; ALL-DAG: insert.w [[R1]][0], $5
750   ; ALL-DAG: neg [[NIDX:\$[0-9]+]], [[BIDX]]
751   ; ALL-DAG: sld.b [[R1]], [[R1]]{{\[}}[[NIDX]]]
752
753   store <2 x i64> %3, <2 x i64>* @v2i64
754   ; ALL-DAG: st.w [[R1]]
755
756   ret void
757 }
758
759 define void @truncstore() nounwind {
760   ; ALL-LABEL: truncstore:
761
762   store volatile <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>, <4 x i8>*@v4i8
763   ; TODO: What code should be emitted?
764
765   ret void
766 }