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>, <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>, <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>, <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>, <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>, <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>, <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>, <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>, <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
357
; Same codegen as above test; scalar is splatted using vld1, so shuffle index is irrelevant.
358
define <4 x float> @check_spr_splat4_lane1(<4 x float> %p, i16 %q) {
359
;CHECK-LABEL: check_spr_splat4_lane1:
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