1 ; RUN: llc -mtriple=arm-eabi -float-abi=soft -mattr=+neon -verify-machineinstrs %s -o - \
4 define <8 x i8> @v_dup8(i8 %A) nounwind {
7 %tmp1 = insertelement <8 x i8> zeroinitializer, i8 %A, i32 0
8 %tmp2 = insertelement <8 x i8> %tmp1, i8 %A, i32 1
9 %tmp3 = insertelement <8 x i8> %tmp2, i8 %A, i32 2
10 %tmp4 = insertelement <8 x i8> %tmp3, i8 %A, i32 3
11 %tmp5 = insertelement <8 x i8> %tmp4, i8 %A, i32 4
12 %tmp6 = insertelement <8 x i8> %tmp5, i8 %A, i32 5
13 %tmp7 = insertelement <8 x i8> %tmp6, i8 %A, i32 6
14 %tmp8 = insertelement <8 x i8> %tmp7, i8 %A, i32 7
18 define <4 x i16> @v_dup16(i16 %A) nounwind {
19 ;CHECK-LABEL: v_dup16:
21 %tmp1 = insertelement <4 x i16> zeroinitializer, i16 %A, i32 0
22 %tmp2 = insertelement <4 x i16> %tmp1, i16 %A, i32 1
23 %tmp3 = insertelement <4 x i16> %tmp2, i16 %A, i32 2
24 %tmp4 = insertelement <4 x i16> %tmp3, i16 %A, i32 3
28 define <2 x i32> @v_dup32(i32 %A) nounwind {
29 ;CHECK-LABEL: v_dup32:
31 %tmp1 = insertelement <2 x i32> zeroinitializer, i32 %A, i32 0
32 %tmp2 = insertelement <2 x i32> %tmp1, i32 %A, i32 1
36 define <2 x float> @v_dupfloat(float %A) nounwind {
37 ;CHECK-LABEL: v_dupfloat:
39 %tmp1 = insertelement <2 x float> zeroinitializer, float %A, i32 0
40 %tmp2 = insertelement <2 x float> %tmp1, float %A, i32 1
44 define <16 x i8> @v_dupQ8(i8 %A) nounwind {
45 ;CHECK-LABEL: v_dupQ8:
47 %tmp1 = insertelement <16 x i8> zeroinitializer, i8 %A, i32 0
48 %tmp2 = insertelement <16 x i8> %tmp1, i8 %A, i32 1
49 %tmp3 = insertelement <16 x i8> %tmp2, i8 %A, i32 2
50 %tmp4 = insertelement <16 x i8> %tmp3, i8 %A, i32 3
51 %tmp5 = insertelement <16 x i8> %tmp4, i8 %A, i32 4
52 %tmp6 = insertelement <16 x i8> %tmp5, i8 %A, i32 5
53 %tmp7 = insertelement <16 x i8> %tmp6, i8 %A, i32 6
54 %tmp8 = insertelement <16 x i8> %tmp7, i8 %A, i32 7
55 %tmp9 = insertelement <16 x i8> %tmp8, i8 %A, i32 8
56 %tmp10 = insertelement <16 x i8> %tmp9, i8 %A, i32 9
57 %tmp11 = insertelement <16 x i8> %tmp10, i8 %A, i32 10
58 %tmp12 = insertelement <16 x i8> %tmp11, i8 %A, i32 11
59 %tmp13 = insertelement <16 x i8> %tmp12, i8 %A, i32 12
60 %tmp14 = insertelement <16 x i8> %tmp13, i8 %A, i32 13
61 %tmp15 = insertelement <16 x i8> %tmp14, i8 %A, i32 14
62 %tmp16 = insertelement <16 x i8> %tmp15, i8 %A, i32 15
66 define <8 x i16> @v_dupQ16(i16 %A) nounwind {
67 ;CHECK-LABEL: v_dupQ16:
69 %tmp1 = insertelement <8 x i16> zeroinitializer, i16 %A, i32 0
70 %tmp2 = insertelement <8 x i16> %tmp1, i16 %A, i32 1
71 %tmp3 = insertelement <8 x i16> %tmp2, i16 %A, i32 2
72 %tmp4 = insertelement <8 x i16> %tmp3, i16 %A, i32 3
73 %tmp5 = insertelement <8 x i16> %tmp4, i16 %A, i32 4
74 %tmp6 = insertelement <8 x i16> %tmp5, i16 %A, i32 5
75 %tmp7 = insertelement <8 x i16> %tmp6, i16 %A, i32 6
76 %tmp8 = insertelement <8 x i16> %tmp7, i16 %A, i32 7
80 define <4 x i32> @v_dupQ32(i32 %A) nounwind {
81 ;CHECK-LABEL: v_dupQ32:
83 %tmp1 = insertelement <4 x i32> zeroinitializer, i32 %A, i32 0
84 %tmp2 = insertelement <4 x i32> %tmp1, i32 %A, i32 1
85 %tmp3 = insertelement <4 x i32> %tmp2, i32 %A, i32 2
86 %tmp4 = insertelement <4 x i32> %tmp3, i32 %A, i32 3
90 define <4 x float> @v_dupQfloat(float %A) nounwind {
91 ;CHECK-LABEL: v_dupQfloat:
93 %tmp1 = insertelement <4 x float> zeroinitializer, float %A, i32 0
94 %tmp2 = insertelement <4 x float> %tmp1, float %A, i32 1
95 %tmp3 = insertelement <4 x float> %tmp2, float %A, i32 2
96 %tmp4 = insertelement <4 x float> %tmp3, float %A, i32 3
100 ; Check to make sure it works with shuffles, too.
102 define <8 x i8> @v_shuffledup8(i8 %A) nounwind {
103 ;CHECK-LABEL: v_shuffledup8:
105 %tmp1 = insertelement <8 x i8> undef, i8 %A, i32 0
106 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> zeroinitializer
110 define <4 x i16> @v_shuffledup16(i16 %A) nounwind {
111 ;CHECK-LABEL: v_shuffledup16:
113 %tmp1 = insertelement <4 x i16> undef, i16 %A, i32 0
114 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> zeroinitializer
118 define <2 x i32> @v_shuffledup32(i32 %A) nounwind {
119 ;CHECK-LABEL: v_shuffledup32:
121 %tmp1 = insertelement <2 x i32> undef, i32 %A, i32 0
122 %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> zeroinitializer
126 define <2 x float> @v_shuffledupfloat(float %A) nounwind {
127 ;CHECK-LABEL: v_shuffledupfloat:
129 %tmp1 = insertelement <2 x float> undef, float %A, i32 0
130 %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> zeroinitializer
131 ret <2 x float> %tmp2
134 define <16 x i8> @v_shuffledupQ8(i8 %A) nounwind {
135 ;CHECK-LABEL: v_shuffledupQ8:
137 %tmp1 = insertelement <16 x i8> undef, i8 %A, i32 0
138 %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> zeroinitializer
142 define <8 x i16> @v_shuffledupQ16(i16 %A) nounwind {
143 ;CHECK-LABEL: v_shuffledupQ16:
145 %tmp1 = insertelement <8 x i16> undef, i16 %A, i32 0
146 %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> zeroinitializer
150 define <4 x i32> @v_shuffledupQ32(i32 %A) nounwind {
151 ;CHECK-LABEL: v_shuffledupQ32:
153 %tmp1 = insertelement <4 x i32> undef, i32 %A, i32 0
154 %tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <4 x i32> zeroinitializer
158 define <4 x float> @v_shuffledupQfloat(float %A) nounwind {
159 ;CHECK-LABEL: v_shuffledupQfloat:
161 %tmp1 = insertelement <4 x float> undef, float %A, i32 0
162 %tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> zeroinitializer
163 ret <4 x float> %tmp2
166 define <8 x i8> @vduplane8(<8 x i8>* %A) nounwind {
167 ;CHECK-LABEL: vduplane8:
169 %tmp1 = load <8 x i8>* %A
170 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
174 define <4 x i16> @vduplane16(<4 x i16>* %A) nounwind {
175 ;CHECK-LABEL: vduplane16:
177 %tmp1 = load <4 x i16>* %A
178 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
182 define <2 x i32> @vduplane32(<2 x i32>* %A) nounwind {
183 ;CHECK-LABEL: vduplane32:
185 %tmp1 = load <2 x i32>* %A
186 %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> < i32 1, i32 1 >
190 define <2 x float> @vduplanefloat(<2 x float>* %A) nounwind {
191 ;CHECK-LABEL: vduplanefloat:
193 %tmp1 = load <2 x float>* %A
194 %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> < i32 1, i32 1 >
195 ret <2 x float> %tmp2
198 define <16 x i8> @vduplaneQ8(<8 x i8>* %A) nounwind {
199 ;CHECK-LABEL: vduplaneQ8:
201 %tmp1 = load <8 x i8>* %A
202 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <16 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
206 define <8 x i16> @vduplaneQ16(<4 x i16>* %A) nounwind {
207 ;CHECK-LABEL: vduplaneQ16:
209 %tmp1 = load <4 x i16>* %A
210 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
214 define <4 x i32> @vduplaneQ32(<2 x i32>* %A) nounwind {
215 ;CHECK-LABEL: vduplaneQ32:
217 %tmp1 = load <2 x i32>* %A
218 %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
222 define <4 x float> @vduplaneQfloat(<2 x float>* %A) nounwind {
223 ;CHECK-LABEL: vduplaneQfloat:
225 %tmp1 = load <2 x float>* %A
226 %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
227 ret <4 x float> %tmp2
230 define <2 x i64> @foo(<2 x i64> %arg0_int64x1_t) nounwind readnone {
232 %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
236 define <2 x i64> @bar(<2 x i64> %arg0_int64x1_t) nounwind readnone {
238 %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 0, i32 0>
242 define <2 x double> @baz(<2 x double> %arg0_int64x1_t) nounwind readnone {
244 %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 1, i32 1>
248 define <2 x double> @qux(<2 x double> %arg0_int64x1_t) nounwind readnone {
250 %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 0, i32 0>
255 ;CHECK-LABEL: redundantVdup:
259 define void @redundantVdup(<8 x i8>* %ptr) nounwind {
260 %1 = insertelement <8 x i8> undef, i8 -128, i32 0
261 %2 = shufflevector <8 x i8> %1, <8 x i8> undef, <8 x i32> zeroinitializer
262 store <8 x i8> %2, <8 x i8>* %ptr, align 8
266 define <4 x i32> @tdupi(i32 %x, i32 %y) {
269 %1 = insertelement <4 x i32> undef, i32 %x, i32 0
270 %2 = insertelement <4 x i32> %1, i32 %x, i32 1
271 %3 = insertelement <4 x i32> %2, i32 %x, i32 2
272 %4 = insertelement <4 x i32> %3, i32 %y, i32 3
276 define <4 x float> @tdupf(float %x, float %y) {
279 %1 = insertelement <4 x float> undef, float %x, i32 0
280 %2 = insertelement <4 x float> %1, float %x, i32 1
281 %3 = insertelement <4 x float> %2, float %x, i32 2
282 %4 = insertelement <4 x float> %3, float %y, i32 3
286 ; This test checks that when splatting an element from a vector into another,
287 ; the value isn't moved out to GPRs first.
288 define <4 x i32> @tduplane(<4 x i32> %invec) {
289 ;CHECK-LABEL: tduplane:
290 ;CHECK-NOT: vmov {{.*}}, d16[1]
291 ;CHECK: vdup.32 {{.*}}, d16[1]
292 %in = extractelement <4 x i32> %invec, i32 1
293 %1 = insertelement <4 x i32> undef, i32 %in, i32 0
294 %2 = insertelement <4 x i32> %1, i32 %in, i32 1
295 %3 = insertelement <4 x i32> %2, i32 %in, i32 2
296 %4 = insertelement <4 x i32> %3, i32 255, i32 3
300 define <2 x float> @check_f32(<4 x float> %v) nounwind {
301 ;CHECK-LABEL: check_f32:
302 ;CHECK: vdup.32 {{.*}}, d{{..}}[1]
303 %x = extractelement <4 x float> %v, i32 3
304 %1 = insertelement <2 x float> undef, float %x, i32 0
305 %2 = insertelement <2 x float> %1, float %x, i32 1
309 define <2 x i32> @check_i32(<4 x i32> %v) nounwind {
310 ;CHECK-LABEL: check_i32:
311 ;CHECK: vdup.32 {{.*}}, d{{..}}[1]
312 %x = extractelement <4 x i32> %v, i32 3
313 %1 = insertelement <2 x i32> undef, i32 %x, i32 0
314 %2 = insertelement <2 x i32> %1, i32 %x, i32 1
318 define <4 x i16> @check_i16(<8 x i16> %v) nounwind {
319 ;CHECK-LABEL: check_i16:
320 ;CHECK: vdup.16 {{.*}}, d{{..}}[3]
321 %x = extractelement <8 x i16> %v, i32 3
322 %1 = insertelement <4 x i16> undef, i16 %x, i32 0
323 %2 = insertelement <4 x i16> %1, i16 %x, i32 1
327 define <8 x i8> @check_i8(<16 x i8> %v) nounwind {
328 ;CHECK-LABEL: check_i8:
329 ;CHECK: vdup.8 {{.*}}, d{{..}}[3]
330 %x = extractelement <16 x i8> %v, i32 3
331 %1 = insertelement <8 x i8> undef, i8 %x, i32 0
332 %2 = insertelement <8 x i8> %1, i8 %x, i32 1
336 ; Check that an SPR splat produces a vdup.
338 define <2 x float> @check_spr_splat2(<2 x float> %p, i16 %q) {
339 ;CHECK-LABEL: check_spr_splat2:
341 %conv = sitofp i16 %q to float
342 %splat.splatinsert = insertelement <2 x float> undef, float %conv, i32 0
343 %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> undef, <2 x i32> zeroinitializer
344 %sub = fsub <2 x float> %splat.splat, %p
348 define <4 x float> @check_spr_splat4(<4 x float> %p, i16 %q) {
349 ;CHECK-LABEL: check_spr_splat4:
351 %conv = sitofp i16 %q to float
352 %splat.splatinsert = insertelement <4 x float> undef, float %conv, i32 0
353 %splat.splat = shufflevector <4 x float> %splat.splatinsert, <4 x float> undef, <4 x i32> zeroinitializer
354 %sub = fsub <4 x float> %splat.splat, %p
358 define <4 x float> @check_spr_splat4_lane1(<4 x float> %p, i16 %q) {
359 ;CHECK-LABEL: check_spr_splat4_lane1:
360 ;CHECK: vdup.32 q{{.*}}, d{{.*}}[1]
361 %conv = sitofp i16 %q to float
362 %splat.splatinsert = insertelement <4 x float> undef, float %conv, i32 1
363 %splat.splat = shufflevector <4 x float> %splat.splatinsert, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
364 %sub = fsub <4 x float> %splat.splat, %p