1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define <4 x float> @test1(<4 x float> %v1) {
6 ; CHECK-NEXT: ret <4 x float> [[V1:%.*]]
8 %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
12 define <4 x float> @test2(<4 x float> %v1) {
13 ; CHECK-LABEL: @test2(
14 ; CHECK-NEXT: ret <4 x float> [[V1:%.*]]
16 %v2 = shufflevector <4 x float> %v1, <4 x float> %v1, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
20 define float @test3(<4 x float> %A, <4 x float> %B, float %f) {
21 ; CHECK-LABEL: @test3(
22 ; CHECK-NEXT: ret float [[F:%.*]]
24 %C = insertelement <4 x float> %A, float %f, i32 0
25 %D = shufflevector <4 x float> %C, <4 x float> %B, <4 x i32> <i32 5, i32 0, i32 2, i32 7>
26 %E = extractelement <4 x float> %D, i32 1
30 define i32 @test4(<4 x i32> %X) {
31 ; CHECK-LABEL: @test4(
32 ; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
33 ; CHECK-NEXT: ret i32 [[R]]
35 %t = shufflevector <4 x i32> %X, <4 x i32> undef, <4 x i32> zeroinitializer
36 %r = extractelement <4 x i32> %t, i32 0
40 define i32 @test5(<4 x i32> %X) {
41 ; CHECK-LABEL: @test5(
42 ; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 3
43 ; CHECK-NEXT: ret i32 [[R]]
45 %t = shufflevector <4 x i32> %X, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 undef, i32 undef>
46 %r = extractelement <4 x i32> %t, i32 0
50 define float @test6(<4 x float> %X) {
51 ; CHECK-LABEL: @test6(
52 ; CHECK-NEXT: [[R:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0
53 ; CHECK-NEXT: ret float [[R]]
55 %X1 = bitcast <4 x float> %X to <4 x i32>
56 %t = shufflevector <4 x i32> %X1, <4 x i32> undef, <4 x i32> zeroinitializer
57 %t2 = bitcast <4 x i32> %t to <4 x float>
58 %r = extractelement <4 x float> %t2, i32 0
62 define float @testvscale6(<vscale x 4 x float> %X) {
63 ; CHECK-LABEL: @testvscale6(
64 ; CHECK-NEXT: [[T2:%.*]] = shufflevector <vscale x 4 x float> [[X:%.*]], <vscale x 4 x float> undef, <vscale x 4 x i32> zeroinitializer
65 ; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x float> [[T2]], i32 0
66 ; CHECK-NEXT: ret float [[R]]
68 %X1 = bitcast <vscale x 4 x float> %X to <vscale x 4 x i32>
69 %t = shufflevector <vscale x 4 x i32> %X1, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer
70 %t2 = bitcast <vscale x 4 x i32> %t to <vscale x 4 x float>
71 %r = extractelement <vscale x 4 x float> %t2, i32 0
76 define <4 x float> @test7(<4 x float> %x) {
77 ; CHECK-LABEL: @test7(
78 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
79 ; CHECK-NEXT: ret <4 x float> [[R]]
81 %r = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> < i32 0, i32 1, i32 6, i32 7 >
85 ; This should turn into a single shuffle.
86 define <4 x float> @test8(<4 x float> %x, <4 x float> %y) {
87 ; CHECK-LABEL: @test8(
88 ; CHECK-NEXT: [[T134:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 1, i32 undef, i32 3, i32 4>
89 ; CHECK-NEXT: ret <4 x float> [[T134]]
91 %t4 = extractelement <4 x float> %x, i32 1
92 %t2 = extractelement <4 x float> %x, i32 3
93 %t1 = extractelement <4 x float> %y, i32 0
94 %t128 = insertelement <4 x float> undef, float %t4, i32 0
95 %t130 = insertelement <4 x float> %t128, float undef, i32 1
96 %t132 = insertelement <4 x float> %t130, float %t2, i32 2
97 %t134 = insertelement <4 x float> %t132, float %t1, i32 3
101 ; Test fold of two shuffles where the first shuffle vectors inputs are a
102 ; different length then the second.
103 define <4 x i8> @test9(<16 x i8> %t6) {
104 ; CHECK-LABEL: @test9(
105 ; CHECK-NEXT: [[T9:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> undef, <4 x i32> <i32 13, i32 9, i32 4, i32 13>
106 ; CHECK-NEXT: ret <4 x i8> [[T9]]
108 %t7 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> < i32 13, i32 9, i32 4, i32 13 >
109 %t9 = shufflevector <4 x i8> %t7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 >
113 ; Same as test9, but make sure that "undef" mask values are not confused with
114 ; mask values of 2*N, where N is the mask length. These shuffles should not
115 ; be folded (because [8,9,4,8] may not be a mask supported by the target).
117 define <4 x i8> @test9a(<16 x i8> %t6) {
118 ; CHECK-LABEL: @test9a(
119 ; CHECK-NEXT: [[T7:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> undef, <4 x i32> <i32 undef, i32 9, i32 4, i32 8>
120 ; CHECK-NEXT: [[T9:%.*]] = shufflevector <4 x i8> [[T7]], <4 x i8> undef, <4 x i32> <i32 3, i32 1, i32 2, i32 undef>
121 ; CHECK-NEXT: ret <4 x i8> [[T9]]
123 %t7 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> < i32 undef, i32 9, i32 4, i32 8 >
124 %t9 = shufflevector <4 x i8> %t7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 >
128 ; Test fold of two shuffles where the first shuffle vectors inputs are a
129 ; different length then the second.
130 define <4 x i8> @test9b(<4 x i8> %t6, <4 x i8> %t7) {
131 ; CHECK-LABEL: @test9b(
132 ; CHECK-NEXT: [[T9:%.*]] = shufflevector <4 x i8> [[T6:%.*]], <4 x i8> [[T7:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
133 ; CHECK-NEXT: ret <4 x i8> [[T9]]
135 %t1 = shufflevector <4 x i8> %t6, <4 x i8> %t7, <8 x i32> <i32 0, i32 1, i32 4, i32 5, i32 4, i32 5, i32 2, i32 3>
136 %t9 = shufflevector <8 x i8> %t1, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
140 ; Redundant vector splats should be removed. Radar 8597790.
141 define <4 x i32> @test10(<4 x i32> %t5) {
142 ; CHECK-LABEL: @test10(
143 ; CHECK-NEXT: [[T7:%.*]] = shufflevector <4 x i32> [[T5:%.*]], <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
144 ; CHECK-NEXT: ret <4 x i32> [[T7]]
146 %t6 = shufflevector <4 x i32> %t5, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
147 %t7 = shufflevector <4 x i32> %t6, <4 x i32> undef, <4 x i32> zeroinitializer
151 ; Test fold of two shuffles where the two shufflevector inputs's op1 are the same.
153 define <8 x i8> @test11(<16 x i8> %t6) {
154 ; CHECK-LABEL: @test11(
155 ; CHECK-NEXT: [[T3:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
156 ; CHECK-NEXT: ret <8 x i8> [[T3]]
158 %t1 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
159 %t2 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
160 %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
164 ; Test fold of two shuffles where the first shufflevector's inputs are the same as the second.
166 define <8 x i8> @test12(<8 x i8> %t6, <8 x i8> %t2) {
167 ; CHECK-LABEL: @test12(
168 ; CHECK-NEXT: [[T3:%.*]] = shufflevector <8 x i8> [[T6:%.*]], <8 x i8> [[T2:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12>
169 ; CHECK-NEXT: ret <8 x i8> [[T3]]
171 %t1 = shufflevector <8 x i8> %t6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7>
172 %t3 = shufflevector <8 x i8> %t1, <8 x i8> %t2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12>
176 ; Test fold of two shuffles where the first shufflevector's inputs are the same as the second.
178 define <8 x i8> @test12a(<8 x i8> %t6, <8 x i8> %t2) {
179 ; CHECK-LABEL: @test12a(
180 ; CHECK-NEXT: [[T3:%.*]] = shufflevector <8 x i8> [[T2:%.*]], <8 x i8> [[T6:%.*]], <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11>
181 ; CHECK-NEXT: ret <8 x i8> [[T3]]
183 %t1 = shufflevector <8 x i8> %t6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7>
184 %t3 = shufflevector <8 x i8> %t2, <8 x i8> %t1, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11>
188 ; The mask length of the 1st shuffle can be reduced to eliminate the 2nd shuffle.
190 define <2 x i8> @extract_subvector_of_shuffle(<2 x i8> %x, <2 x i8> %y) {
191 ; CHECK-LABEL: @extract_subvector_of_shuffle(
192 ; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 2>
193 ; CHECK-NEXT: ret <2 x i8> [[EXTRACT_SUBV]]
195 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <3 x i32> <i32 0, i32 2, i32 0>
196 %extract_subv = shufflevector <3 x i8> %shuf, <3 x i8> undef, <2 x i32> <i32 0, i32 1>
197 ret <2 x i8> %extract_subv
200 ; Undef elements in either mask are ok. Undefs from the 2nd shuffle mask should propagate to the new shuffle.
201 ; The type of the inputs does not have to match the output type.
203 define <4 x i8> @extract_subvector_of_shuffle_undefs_types(<2 x i8> %x, <2 x i8> %y) {
204 ; CHECK-LABEL: @extract_subvector_of_shuffle_undefs_types(
205 ; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <4 x i32> <i32 undef, i32 2, i32 0, i32 undef>
206 ; CHECK-NEXT: ret <4 x i8> [[EXTRACT_SUBV]]
208 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0>
209 %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
210 ret <4 x i8> %extract_subv
213 ; Extra uses are not ok - we only do the transform when we can eliminate an instruction.
215 declare void @use_v5i8(<5 x i8>)
217 define <4 x i8> @extract_subvector_of_shuffle_extra_use(<2 x i8> %x, <2 x i8> %y) {
218 ; CHECK-LABEL: @extract_subvector_of_shuffle_extra_use(
219 ; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0>
220 ; CHECK-NEXT: call void @use_v5i8(<5 x i8> [[SHUF]])
221 ; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <5 x i8> [[SHUF]], <5 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
222 ; CHECK-NEXT: ret <4 x i8> [[EXTRACT_SUBV]]
224 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0>
225 call void @use_v5i8(<5 x i8> %shuf)
226 %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
227 ret <4 x i8> %extract_subv
230 define <2 x i8> @test13a(i8 %x1, i8 %x2) {
231 ; CHECK-LABEL: @test13a(
232 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> undef, i8 [[X1:%.*]], i32 1
233 ; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X2:%.*]], i32 0
234 ; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i8> [[TMP2]], <i8 7, i8 5>
235 ; CHECK-NEXT: ret <2 x i8> [[TMP3]]
237 %A = insertelement <2 x i8> undef, i8 %x1, i32 0
238 %B = insertelement <2 x i8> %A, i8 %x2, i32 1
239 %C = add <2 x i8> %B, <i8 5, i8 7>
240 %D = shufflevector <2 x i8> %C, <2 x i8> undef, <2 x i32> <i32 1, i32 0>
244 ; Increasing length of vector ops is not a good canonicalization.
246 define <3 x i32> @add_wider(i32 %y, i32 %z) {
247 ; CHECK-LABEL: @add_wider(
248 ; CHECK-NEXT: [[I0:%.*]] = insertelement <2 x i32> undef, i32 [[Y:%.*]], i32 0
249 ; CHECK-NEXT: [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i32 1
250 ; CHECK-NEXT: [[A:%.*]] = add <2 x i32> [[I1]], <i32 255, i32 255>
251 ; CHECK-NEXT: [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef>
252 ; CHECK-NEXT: ret <3 x i32> [[EXT]]
254 %i0 = insertelement <2 x i32> undef, i32 %y, i32 0
255 %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1
256 %a = add <2 x i32> %i1, <i32 255, i32 255>
257 %ext = shufflevector <2 x i32> %a, <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef>
261 ; Increasing length of vector ops must be safe from illegal undef propagation.
263 define <3 x i32> @div_wider(i32 %y, i32 %z) {
264 ; CHECK-LABEL: @div_wider(
265 ; CHECK-NEXT: [[I0:%.*]] = insertelement <2 x i32> undef, i32 [[Y:%.*]], i32 0
266 ; CHECK-NEXT: [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i32 1
267 ; CHECK-NEXT: [[A:%.*]] = sdiv <2 x i32> [[I1]], <i32 255, i32 255>
268 ; CHECK-NEXT: [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef>
269 ; CHECK-NEXT: ret <3 x i32> [[EXT]]
271 %i0 = insertelement <2 x i32> undef, i32 %y, i32 0
272 %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1
273 %a = sdiv <2 x i32> %i1, <i32 255, i32 255>
274 %ext = shufflevector <2 x i32> %a, <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef>
278 ; Increasing length of insertelements (no math ops) is a good canonicalization.
280 define <3 x i8> @fold_inselts_with_widening_shuffle(i8 %x, i8 %y) {
281 ; CHECK-LABEL: @fold_inselts_with_widening_shuffle(
282 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <3 x i8> undef, i8 [[X:%.*]], i32 0
283 ; CHECK-NEXT: [[TMP2:%.*]] = insertelement <3 x i8> [[TMP1]], i8 [[Y:%.*]], i32 1
284 ; CHECK-NEXT: ret <3 x i8> [[TMP2]]
286 %ins0 = insertelement <2 x i8> undef, i8 %x, i32 0
287 %ins1 = insertelement <2 x i8> %ins0, i8 %y, i32 1
288 %widen = shufflevector <2 x i8> %ins1, <2 x i8> undef, <3 x i32> <i32 0, i32 1, i32 undef>
292 define <2 x i8> @test13b(i8 %x) {
293 ; CHECK-LABEL: @test13b(
294 ; CHECK-NEXT: [[B:%.*]] = insertelement <2 x i8> undef, i8 [[X:%.*]], i32 1
295 ; CHECK-NEXT: ret <2 x i8> [[B]]
297 %A = insertelement <2 x i8> undef, i8 %x, i32 0
298 %B = shufflevector <2 x i8> %A, <2 x i8> undef, <2 x i32> <i32 undef, i32 0>
302 define <2 x i8> @test13c(i8 %x1, i8 %x2) {
303 ; CHECK-LABEL: @test13c(
304 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> undef, i8 [[X1:%.*]], i32 0
305 ; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X2:%.*]], i32 1
306 ; CHECK-NEXT: ret <2 x i8> [[TMP2]]
308 %A = insertelement <4 x i8> undef, i8 %x1, i32 0
309 %B = insertelement <4 x i8> %A, i8 %x2, i32 2
310 %C = shufflevector <4 x i8> %B, <4 x i8> undef, <2 x i32> <i32 0, i32 2>
314 define void @test14(i16 %conv10) {
315 ; CHECK-LABEL: @test14(
316 ; CHECK-NEXT: store <4 x i16> <i16 undef, i16 undef, i16 undef, i16 23>, <4 x i16>* undef, align 8
317 ; CHECK-NEXT: ret void
319 %t = alloca <4 x i16>, align 8
320 %vecinit6 = insertelement <4 x i16> undef, i16 23, i32 3
321 store <4 x i16> %vecinit6, <4 x i16>* undef
322 %t1 = load <4 x i16>, <4 x i16>* undef
323 %vecinit11 = insertelement <4 x i16> undef, i16 %conv10, i32 3
324 %div = udiv <4 x i16> %t1, %vecinit11
325 store <4 x i16> %div, <4 x i16>* %t
326 %t4 = load <4 x i16>, <4 x i16>* %t
327 %t5 = shufflevector <4 x i16> %t4, <4 x i16> undef, <2 x i32> <i32 2, i32 0>
328 %cmp = icmp ule <2 x i16> %t5, undef
329 %sext = sext <2 x i1> %cmp to <2 x i16>
333 ; Check that sequences of insert/extract element are
334 ; collapsed into valid shuffle instruction with correct shuffle indexes.
336 define <4 x float> @test15a(<4 x float> %LHS, <4 x float> %RHS) {
337 ; CHECK-LABEL: @test15a(
338 ; CHECK-NEXT: [[T4:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 0, i32 6, i32 6>
339 ; CHECK-NEXT: ret <4 x float> [[T4]]
341 %t1 = extractelement <4 x float> %LHS, i32 0
342 %t2 = insertelement <4 x float> %RHS, float %t1, i32 1
343 %t3 = extractelement <4 x float> %RHS, i32 2
344 %t4 = insertelement <4 x float> %t2, float %t3, i32 3
348 define <4 x float> @test15b(<4 x float> %LHS, <4 x float> %RHS) {
349 ; CHECK-LABEL: @test15b(
350 ; CHECK-NEXT: [[T5:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 3, i32 6, i32 6>
351 ; CHECK-NEXT: ret <4 x float> [[T5]]
353 %t0 = extractelement <4 x float> %LHS, i32 3
354 %t1 = insertelement <4 x float> %RHS, float %t0, i32 0
355 %t2 = extractelement <4 x float> %t1, i32 0
356 %t3 = insertelement <4 x float> %RHS, float %t2, i32 1
357 %t4 = extractelement <4 x float> %RHS, i32 2
358 %t5 = insertelement <4 x float> %t3, float %t4, i32 3
362 define <1 x i32> @test16a(i32 %ele) {
363 ; CHECK-LABEL: @test16a(
364 ; CHECK-NEXT: ret <1 x i32> <i32 2>
366 %t0 = insertelement <2 x i32> <i32 1, i32 undef>, i32 %ele, i32 1
367 %t1 = shl <2 x i32> %t0, <i32 1, i32 1>
368 %t2 = shufflevector <2 x i32> %t1, <2 x i32> undef, <1 x i32> <i32 0>
372 define <4 x i8> @test16b(i8 %ele) {
373 ; CHECK-LABEL: @test16b(
374 ; CHECK-NEXT: ret <4 x i8> <i8 2, i8 2, i8 2, i8 2>
376 %t0 = insertelement <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 undef, i8 1>, i8 %ele, i32 6
377 %t1 = shl <8 x i8> %t0, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
378 %t2 = shufflevector <8 x i8> %t1, <8 x i8> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
382 ; If composition of two shuffles is identity, shuffles can be removed.
383 define <4 x i32> @shuffle_17ident(<4 x i32> %v) {
384 ; CHECK-LABEL: @shuffle_17ident(
385 ; CHECK-NEXT: ret <4 x i32> [[V:%.*]]
387 %shuffle = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
388 %shuffle2 = shufflevector <4 x i32> %shuffle, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 1, i32 2>
389 ret <4 x i32> %shuffle2
392 ; swizzle can be put after operation
393 define <4 x i32> @shuffle_17and(<4 x i32> %v1, <4 x i32> %v2) {
394 ; CHECK-LABEL: @shuffle_17and(
395 ; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[V1:%.*]], [[V2:%.*]]
396 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
397 ; CHECK-NEXT: ret <4 x i32> [[R]]
399 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
400 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
401 %r = and <4 x i32> %t1, %t2
405 declare void @use(<2 x float>)
407 ; One extra use is ok to transform.
409 define <2 x float> @shuffle_fadd_multiuse(<2 x float> %v1, <2 x float> %v2) {
410 ; CHECK-LABEL: @shuffle_fadd_multiuse(
411 ; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
412 ; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[V1]], [[V2:%.*]]
413 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
414 ; CHECK-NEXT: call void @use(<2 x float> [[T1]])
415 ; CHECK-NEXT: ret <2 x float> [[R]]
417 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0>
418 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0>
419 %r = fadd <2 x float> %t1, %t2
420 call void @use(<2 x float> %t1)
424 define <2 x float> @shuffle_fdiv_multiuse(<2 x float> %v1, <2 x float> %v2) {
425 ; CHECK-LABEL: @shuffle_fdiv_multiuse(
426 ; CHECK-NEXT: [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
427 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[V1:%.*]], [[V2]]
428 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
429 ; CHECK-NEXT: call void @use(<2 x float> [[T2]])
430 ; CHECK-NEXT: ret <2 x float> [[R]]
432 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0>
433 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0>
434 %r = fdiv <2 x float> %t1, %t2
435 call void @use(<2 x float> %t2)
439 ; But 2 extra uses would require an extra instruction.
441 define <2 x float> @shuffle_fsub_multiuse(<2 x float> %v1, <2 x float> %v2) {
442 ; CHECK-LABEL: @shuffle_fsub_multiuse(
443 ; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
444 ; CHECK-NEXT: [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
445 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[T1]], [[T2]]
446 ; CHECK-NEXT: call void @use(<2 x float> [[T1]])
447 ; CHECK-NEXT: call void @use(<2 x float> [[T2]])
448 ; CHECK-NEXT: ret <2 x float> [[R]]
450 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0>
451 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0>
452 %r = fsub <2 x float> %t1, %t2
453 call void @use(<2 x float> %t1)
454 call void @use(<2 x float> %t2)
458 define <4 x i32> @shuffle_17add(<4 x i32> %v1, <4 x i32> %v2) {
459 ; CHECK-LABEL: @shuffle_17add(
460 ; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[V1:%.*]], [[V2:%.*]]
461 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
462 ; CHECK-NEXT: ret <4 x i32> [[R]]
464 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
465 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
466 %r = add <4 x i32> %t1, %t2
470 define <4 x i32> @shuffle_17addnsw(<4 x i32> %v1, <4 x i32> %v2) {
471 ; CHECK-LABEL: @shuffle_17addnsw(
472 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw <4 x i32> [[V1:%.*]], [[V2:%.*]]
473 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
474 ; CHECK-NEXT: ret <4 x i32> [[R]]
476 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
477 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
478 %r = add nsw <4 x i32> %t1, %t2
482 define <4 x i32> @shuffle_17addnuw(<4 x i32> %v1, <4 x i32> %v2) {
483 ; CHECK-LABEL: @shuffle_17addnuw(
484 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw <4 x i32> [[V1:%.*]], [[V2:%.*]]
485 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
486 ; CHECK-NEXT: ret <4 x i32> [[R]]
488 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
489 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
490 %r = add nuw <4 x i32> %t1, %t2
494 define <4 x float> @shuffle_17fsub_fast(<4 x float> %v1, <4 x float> %v2) {
495 ; CHECK-LABEL: @shuffle_17fsub_fast(
496 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast <4 x float> [[V1:%.*]], [[V2:%.*]]
497 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
498 ; CHECK-NEXT: ret <4 x float> [[R]]
500 %t1 = shufflevector <4 x float> %v1, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
501 %t2 = shufflevector <4 x float> %v2, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
502 %r = fsub fast <4 x float> %t1, %t2
506 define <4 x i32> @add_const(<4 x i32> %v) {
507 ; CHECK-LABEL: @add_const(
508 ; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[V:%.*]], <i32 44, i32 41, i32 42, i32 43>
509 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
510 ; CHECK-NEXT: ret <4 x i32> [[R]]
512 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
513 %r = add <4 x i32> %t1, <i32 41, i32 42, i32 43, i32 44>
517 define <4 x i32> @sub_const(<4 x i32> %v) {
518 ; CHECK-LABEL: @sub_const(
519 ; CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> <i32 44, i32 43, i32 42, i32 41>, [[V:%.*]]
520 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
521 ; CHECK-NEXT: ret <4 x i32> [[R]]
523 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
524 %r = sub <4 x i32> <i32 41, i32 42, i32 43, i32 44>, %t1
528 ; Math before shuffle requires an extra shuffle.
530 define <2 x float> @fadd_const_multiuse(<2 x float> %v) {
531 ; CHECK-LABEL: @fadd_const_multiuse(
532 ; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 0>
533 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01>
534 ; CHECK-NEXT: call void @use(<2 x float> [[T1]])
535 ; CHECK-NEXT: ret <2 x float> [[R]]
537 %t1 = shufflevector <2 x float> %v, <2 x float> undef, <2 x i32> <i32 1, i32 0>
538 %r = fadd <2 x float> %t1, <float 41.0, float 42.0>
539 call void @use(<2 x float> %t1)
543 ; Math before splat allows replacing constant elements with undef lanes.
545 define <4 x i32> @mul_const_splat(<4 x i32> %v) {
546 ; CHECK-LABEL: @mul_const_splat(
547 ; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], <i32 poison, i32 42, i32 poison, i32 poison>
548 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
549 ; CHECK-NEXT: ret <4 x i32> [[R]]
551 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
552 %r = mul <4 x i32> <i32 42, i32 42, i32 42, i32 42>, %t1
556 ; Take 2 elements of a vector and shift each of those by a different amount
558 define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) {
559 ; CHECK-LABEL: @lshr_const_half_splat(
560 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 undef, i32 8, i32 9, i32 undef>, [[V:%.*]]
561 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
562 ; CHECK-NEXT: ret <4 x i32> [[R]]
564 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
565 %r = lshr <4 x i32> <i32 8, i32 8, i32 9, i32 9>, %t1
569 ; We can't change this because there's no pre-shuffle version of the fmul constant.
571 define <2 x float> @fmul_const_invalid_constant(<2 x float> %v) {
572 ; CHECK-LABEL: @fmul_const_invalid_constant(
573 ; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> undef, <2 x i32> zeroinitializer
574 ; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01>
575 ; CHECK-NEXT: ret <2 x float> [[R]]
577 %t1 = shufflevector <2 x float> %v, <2 x float> undef, <2 x i32> <i32 0, i32 0>
578 %r = fmul <2 x float> %t1, <float 41.0, float 42.0>
582 ; Reduce the width of the binop by moving it ahead of a shuffle.
584 define <4 x i8> @widening_shuffle_add_1(<2 x i8> %x) {
585 ; CHECK-LABEL: @widening_shuffle_add_1(
586 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 42, i8 43>
587 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
588 ; CHECK-NEXT: ret <4 x i8> [[R]]
590 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
591 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
595 ; Reduce the width of the binop by moving it ahead of a shuffle.
597 define <4 x i8> @widening_shuffle_add_2(<2 x i8> %x) {
598 ; CHECK-LABEL: @widening_shuffle_add_2(
599 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 43, i8 42>
600 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> undef, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
601 ; CHECK-NEXT: ret <4 x i8> [[R]]
603 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
604 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
608 ; Negative test - widening shuffles have the same mask/constant constraint as non-size-changing shuffles.
610 define <4 x i8> @widening_shuffle_add_invalid_constant(<2 x i8> %x) {
611 ; CHECK-LABEL: @widening_shuffle_add_invalid_constant(
612 ; CHECK-NEXT: [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> undef, <4 x i32> <i32 1, i32 1, i32 undef, i32 undef>
613 ; CHECK-NEXT: [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45>
614 ; CHECK-NEXT: ret <4 x i8> [[R]]
616 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 1, i32 1, i32 undef, i32 undef>
617 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
621 ; Negative test - widening shuffles have an additional constraint: they must not extend with anything but undefs.
623 define <4 x i8> @widening_shuffle_add_invalid_mask(<2 x i8> %x) {
624 ; CHECK-LABEL: @widening_shuffle_add_invalid_mask(
625 ; CHECK-NEXT: [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 0>
626 ; CHECK-NEXT: [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45>
627 ; CHECK-NEXT: ret <4 x i8> [[R]]
629 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 0>
630 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
634 ; A binop that produces undef in the high lanes can be moved before the shuffle.
635 ; This is ok because 'shl C, undef --> undef'.
637 define <4 x i16> @widening_shuffle_shl_constant_op0(<2 x i16> %v) {
638 ; CHECK-LABEL: @widening_shuffle_shl_constant_op0(
639 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> <i16 42, i16 -42>, [[V:%.*]]
640 ; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
641 ; CHECK-NEXT: ret <4 x i16> [[BO]]
643 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
644 %bo = shl <4 x i16> <i16 42, i16 -42, i16 -1, i16 -1>, %shuf
648 ; A binop that produces undef in the high lanes can be moved before the shuffle.
649 ; This is ok because 'shl undef, 0 --> undef'.
651 define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
652 ; CHECK-LABEL: @widening_shuffle_shl_constant_op1(
653 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
654 ; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
655 ; CHECK-NEXT: ret <4 x i16> [[BO]]
657 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
658 %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 0, i16 0>
662 ; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
663 ; This is not ok because 'shl undef, 1 (or 2)' --> 0' but moving the shuffle results in undef instead.
665 define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
666 ; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
667 ; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
668 ; CHECK-NEXT: [[BO:%.*]] = shl <4 x i16> [[SHUF]], <i16 2, i16 4, i16 1, i16 2>
669 ; CHECK-NEXT: ret <4 x i16> [[BO]]
671 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
672 %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 1, i16 2>
676 ; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
677 ; This is not ok because 'or -1, undef --> -1' but moving the shuffle results in undef instead.
679 define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
680 ; CHECK-LABEL: @widening_shuffle_or(
681 ; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
682 ; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
683 ; CHECK-NEXT: ret <4 x i16> [[BO]]
685 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
686 %bo = or <4 x i16> %shuf, <i16 42, i16 -42, i16 -1, i16 -1>
690 define <4 x i32> @shuffle_17add2(<4 x i32> %v) {
691 ; CHECK-LABEL: @shuffle_17add2(
692 ; CHECK-NEXT: [[TMP1:%.*]] = shl <4 x i32> [[V:%.*]], <i32 1, i32 1, i32 1, i32 1>
693 ; CHECK-NEXT: ret <4 x i32> [[TMP1]]
695 %t1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
696 %t2 = add <4 x i32> %t1, %t1
697 %r = shufflevector <4 x i32> %t2, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
701 define <4 x i32> @shuffle_17mulsplat(<4 x i32> %v) {
702 ; CHECK-LABEL: @shuffle_17mulsplat(
703 ; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], [[V]]
704 ; CHECK-NEXT: [[M1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> undef, <4 x i32> zeroinitializer
705 ; CHECK-NEXT: ret <4 x i32> [[M1]]
707 %s1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer
708 %m1 = mul <4 x i32> %s1, %s1
709 %s2 = shufflevector <4 x i32> %m1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
713 ; Do not reorder shuffle and binop if LHS of shuffles are of different size
714 define <2 x i32> @pr19717(<4 x i32> %in0, <2 x i32> %in1) {
715 ; CHECK-LABEL: @pr19717(
716 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[IN0:%.*]], <4 x i32> undef, <2 x i32> zeroinitializer
717 ; CHECK-NEXT: [[SHUFFLE4:%.*]] = shufflevector <2 x i32> [[IN1:%.*]], <2 x i32> undef, <2 x i32> zeroinitializer
718 ; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SHUFFLE]], [[SHUFFLE4]]
719 ; CHECK-NEXT: ret <2 x i32> [[MUL]]
721 %shuffle = shufflevector <4 x i32> %in0, <4 x i32> %in0, <2 x i32> zeroinitializer
722 %shuffle4 = shufflevector <2 x i32> %in1, <2 x i32> %in1, <2 x i32> zeroinitializer
723 %mul = mul <2 x i32> %shuffle, %shuffle4
727 define <4 x i16> @pr19717a(<8 x i16> %in0, <8 x i16> %in1) {
728 ; CHECK-LABEL: @pr19717a(
729 ; CHECK-NEXT: [[TMP1:%.*]] = mul <8 x i16> [[IN0:%.*]], [[IN1:%.*]]
730 ; CHECK-NEXT: [[MUL:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> undef, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
731 ; CHECK-NEXT: ret <4 x i16> [[MUL]]
733 %shuffle = shufflevector <8 x i16> %in0, <8 x i16> %in0, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
734 %shuffle1 = shufflevector <8 x i16> %in1, <8 x i16> %in1, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
735 %mul = mul <4 x i16> %shuffle, %shuffle1
739 define <8 x i8> @pr19730(<16 x i8> %in0) {
740 ; CHECK-LABEL: @pr19730(
741 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <16 x i8> [[IN0:%.*]], <16 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
742 ; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <8 x i8> [[SHUFFLE]], <8 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
743 ; CHECK-NEXT: ret <8 x i8> [[SHUFFLE1]]
745 %shuffle = shufflevector <16 x i8> %in0, <16 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
746 %shuffle1 = shufflevector <8 x i8> %shuffle, <8 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
747 ret <8 x i8> %shuffle1
750 define i32 @pr19737(<4 x i32> %in0) {
751 ; CHECK-LABEL: @pr19737(
752 ; CHECK-NEXT: [[RV:%.*]] = extractelement <4 x i32> [[IN0:%.*]], i32 0
753 ; CHECK-NEXT: ret i32 [[RV]]
755 %shuffle.i = shufflevector <4 x i32> zeroinitializer, <4 x i32> %in0, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
756 %neg.i = xor <4 x i32> %shuffle.i, <i32 -1, i32 -1, i32 -1, i32 -1>
757 %and.i = and <4 x i32> %in0, %neg.i
758 %rv = extractelement <4 x i32> %and.i, i32 0
762 ; In PR20059 ( http://llvm.org/pr20059 ), shufflevector operations are reordered/removed
763 ; for an srem operation. This is not a valid optimization because it may cause a trap
766 define <4 x i32> @pr20059(<4 x i32> %p1, <4 x i32> %p2) {
767 ; CHECK-LABEL: @pr20059(
768 ; CHECK-NEXT: [[SPLAT1:%.*]] = shufflevector <4 x i32> [[P1:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
769 ; CHECK-NEXT: [[SPLAT2:%.*]] = shufflevector <4 x i32> [[P2:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
770 ; CHECK-NEXT: [[RETVAL:%.*]] = srem <4 x i32> [[SPLAT1]], [[SPLAT2]]
771 ; CHECK-NEXT: ret <4 x i32> [[RETVAL]]
773 %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer
774 %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer
775 %retval = srem <4 x i32> %splat1, %splat2
776 ret <4 x i32> %retval
779 define <4 x i32> @pr20114(<4 x i32> %__mask) {
780 ; CHECK-LABEL: @pr20114(
781 ; CHECK-NEXT: [[MASK01_I:%.*]] = shufflevector <4 x i32> [[__MASK:%.*]], <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 1, i32 1>
782 ; CHECK-NEXT: [[MASKED_NEW_I_I_I:%.*]] = and <4 x i32> [[MASK01_I]], bitcast (<2 x i64> <i64 ptrtoint (<4 x i32> (<4 x i32>)* @pr20114 to i64), i64 ptrtoint (<4 x i32> (<4 x i32>)* @pr20114 to i64)> to <4 x i32>)
783 ; CHECK-NEXT: ret <4 x i32> [[MASKED_NEW_I_I_I]]
785 %mask01.i = shufflevector <4 x i32> %__mask, <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 1, i32 1>
786 %masked_new.i.i.i = and <4 x i32> bitcast (<2 x i64> <i64 ptrtoint (<4 x i32> (<4 x i32>)* @pr20114 to i64), i64 ptrtoint (<4 x i32> (<4 x i32>)* @pr20114 to i64)> to <4 x i32>), %mask01.i
787 ret <4 x i32> %masked_new.i.i.i
790 define <2 x i32*> @pr23113(<4 x i32*> %A) {
791 ; CHECK-LABEL: @pr23113(
792 ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32*> [[A:%.*]], <4 x i32*> undef, <2 x i32> <i32 0, i32 1>
793 ; CHECK-NEXT: ret <2 x i32*> [[TMP1]]
795 %1 = shufflevector <4 x i32*> %A, <4 x i32*> undef, <2 x i32> <i32 0, i32 1>
799 ; Unused lanes in the new binop should not kill the entire op (although it may simplify anyway as shown here).
801 define <2 x i32> @PR37648(<2 x i32> %x) {
802 ; CHECK-LABEL: @PR37648(
803 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
805 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
806 %r = urem <2 x i32> %splat, <i32 1, i32 1>
810 ; Test shuffle followed by binop with splat constant for all 18 binop opcodes.
811 ; Test with constant as operand 0 and operand 1 for non-commutative opcodes.
813 define <2 x i32> @add_splat_constant(<2 x i32> %x) {
814 ; CHECK-LABEL: @add_splat_constant(
815 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 42, i32 poison>
816 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
817 ; CHECK-NEXT: ret <2 x i32> [[R]]
819 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
820 %r = add <2 x i32> %splat, <i32 42, i32 42>
824 define <2 x i32> @sub_splat_constant0(<2 x i32> %x) {
825 ; CHECK-LABEL: @sub_splat_constant0(
826 ; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i32> <i32 42, i32 poison>, [[X:%.*]]
827 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
828 ; CHECK-NEXT: ret <2 x i32> [[R]]
830 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
831 %r = sub <2 x i32> <i32 42, i32 42>, %splat
835 define <2 x i32> @sub_splat_constant1(<2 x i32> %x) {
836 ; CHECK-LABEL: @sub_splat_constant1(
837 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 -42, i32 poison>
838 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
839 ; CHECK-NEXT: ret <2 x i32> [[R]]
841 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
842 %r = sub <2 x i32> %splat, <i32 42, i32 42>
846 define <2 x i32> @mul_splat_constant(<2 x i32> %x) {
847 ; CHECK-LABEL: @mul_splat_constant(
848 ; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], <i32 42, i32 poison>
849 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
850 ; CHECK-NEXT: ret <2 x i32> [[R]]
852 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
853 %r = mul <2 x i32> %splat, <i32 42, i32 42>
857 define <2 x i32> @shl_splat_constant0(<2 x i32> %x) {
858 ; CHECK-LABEL: @shl_splat_constant0(
859 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
860 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
861 ; CHECK-NEXT: ret <2 x i32> [[R]]
863 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
864 %r = shl <2 x i32> <i32 5, i32 5>, %splat
868 define <2 x i32> @shl_splat_constant1(<2 x i32> %x) {
869 ; CHECK-LABEL: @shl_splat_constant1(
870 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 0>
871 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
872 ; CHECK-NEXT: ret <2 x i32> [[R]]
874 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
875 %r = shl <2 x i32> %splat, <i32 5, i32 5>
879 define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) {
880 ; CHECK-LABEL: @ashr_splat_constant0(
881 ; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
882 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
883 ; CHECK-NEXT: ret <2 x i32> [[R]]
885 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
886 %r = ashr <2 x i32> <i32 5, i32 5>, %splat
890 define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) {
891 ; CHECK-LABEL: @ashr_splat_constant1(
892 ; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 0>
893 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
894 ; CHECK-NEXT: ret <2 x i32> [[R]]
896 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
897 %r = ashr <2 x i32> %splat, <i32 5, i32 5>
901 define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) {
902 ; CHECK-LABEL: @lshr_splat_constant0(
903 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
904 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
905 ; CHECK-NEXT: ret <2 x i32> [[R]]
907 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
908 %r = lshr <2 x i32> <i32 5, i32 5>, %splat
912 define <2 x i32> @lshr_splat_constant1(<2 x i32> %x) {
913 ; CHECK-LABEL: @lshr_splat_constant1(
914 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 0>
915 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
916 ; CHECK-NEXT: ret <2 x i32> [[R]]
918 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
919 %r = lshr <2 x i32> %splat, <i32 5, i32 5>
923 define <2 x i32> @urem_splat_constant0(<2 x i32> %x) {
924 ; CHECK-LABEL: @urem_splat_constant0(
925 ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> undef, <2 x i32> zeroinitializer
926 ; CHECK-NEXT: [[R:%.*]] = urem <2 x i32> <i32 42, i32 42>, [[SPLAT]]
927 ; CHECK-NEXT: ret <2 x i32> [[R]]
929 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
930 %r = urem <2 x i32> <i32 42, i32 42>, %splat
934 define <2 x i32> @urem_splat_constant1(<2 x i32> %x) {
935 ; CHECK-LABEL: @urem_splat_constant1(
936 ; CHECK-NEXT: [[TMP1:%.*]] = urem <2 x i32> [[X:%.*]], <i32 42, i32 1>
937 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
938 ; CHECK-NEXT: ret <2 x i32> [[R]]
940 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
941 %r = urem <2 x i32> %splat, <i32 42, i32 42>
945 define <2 x i32> @srem_splat_constant0(<2 x i32> %x) {
946 ; CHECK-LABEL: @srem_splat_constant0(
947 ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> undef, <2 x i32> zeroinitializer
948 ; CHECK-NEXT: [[R:%.*]] = srem <2 x i32> <i32 42, i32 42>, [[SPLAT]]
949 ; CHECK-NEXT: ret <2 x i32> [[R]]
951 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
952 %r = srem <2 x i32> <i32 42, i32 42>, %splat
956 define <2 x i32> @srem_splat_constant1(<2 x i32> %x) {
957 ; CHECK-LABEL: @srem_splat_constant1(
958 ; CHECK-NEXT: [[TMP1:%.*]] = srem <2 x i32> [[X:%.*]], <i32 42, i32 1>
959 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
960 ; CHECK-NEXT: ret <2 x i32> [[R]]
962 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
963 %r = srem <2 x i32> %splat, <i32 42, i32 42>
967 define <2 x i32> @udiv_splat_constant0(<2 x i32> %x) {
968 ; CHECK-LABEL: @udiv_splat_constant0(
969 ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> undef, <2 x i32> zeroinitializer
970 ; CHECK-NEXT: [[R:%.*]] = udiv <2 x i32> <i32 42, i32 42>, [[SPLAT]]
971 ; CHECK-NEXT: ret <2 x i32> [[R]]
973 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
974 %r = udiv <2 x i32> <i32 42, i32 42>, %splat
978 define <2 x i32> @udiv_splat_constant1(<2 x i32> %x) {
979 ; CHECK-LABEL: @udiv_splat_constant1(
980 ; CHECK-NEXT: [[TMP1:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 42, i32 1>
981 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
982 ; CHECK-NEXT: ret <2 x i32> [[R]]
984 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
985 %r = udiv <2 x i32> %splat, <i32 42, i32 42>
989 define <2 x i32> @sdiv_splat_constant0(<2 x i32> %x) {
990 ; CHECK-LABEL: @sdiv_splat_constant0(
991 ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> undef, <2 x i32> zeroinitializer
992 ; CHECK-NEXT: [[R:%.*]] = sdiv <2 x i32> <i32 42, i32 42>, [[SPLAT]]
993 ; CHECK-NEXT: ret <2 x i32> [[R]]
995 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
996 %r = sdiv <2 x i32> <i32 42, i32 42>, %splat
1000 define <2 x i32> @sdiv_splat_constant1(<2 x i32> %x) {
1001 ; CHECK-LABEL: @sdiv_splat_constant1(
1002 ; CHECK-NEXT: [[TMP1:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 42, i32 1>
1003 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
1004 ; CHECK-NEXT: ret <2 x i32> [[R]]
1006 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
1007 %r = sdiv <2 x i32> %splat, <i32 42, i32 42>
1011 define <2 x i32> @and_splat_constant(<2 x i32> %x) {
1012 ; CHECK-LABEL: @and_splat_constant(
1013 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1014 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
1015 ; CHECK-NEXT: ret <2 x i32> [[R]]
1017 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
1018 %r = and <2 x i32> %splat, <i32 42, i32 42>
1022 ; AND does not fold to undef for undef operands, we cannot move it
1023 ; across a shuffle with undef masks.
1024 define <4 x i16> @and_constant_mask_undef(<4 x i16> %add) {
1025 ; CHECK-LABEL: @and_constant_mask_undef(
1026 ; CHECK-NEXT: entry:
1027 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1028 ; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
1029 ; CHECK-NEXT: ret <4 x i16> [[AND]]
1032 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1033 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1037 ; AND does not fold to undef for undef operands, we cannot move it
1038 ; across a shuffle with undef masks.
1039 define <4 x i16> @and_constant_mask_undef_2(<4 x i16> %add) {
1040 ; CHECK-LABEL: @and_constant_mask_undef_2(
1041 ; CHECK-NEXT: entry:
1042 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 undef>
1043 ; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
1044 ; CHECK-NEXT: ret <4 x i16> [[AND]]
1047 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 undef>
1048 %and = and <4 x i16> %shuffle, <i16 -1, i16 -1, i16 -1, i16 -0>
1052 ; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1053 define <4 x i16> @and_constant_mask_undef_3(<4 x i16> %add) {
1054 ; CHECK-LABEL: @and_constant_mask_undef_3(
1055 ; CHECK-NEXT: entry:
1056 ; CHECK-NEXT: ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
1059 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
1060 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 0, i16 -1>
1064 ; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1065 define <4 x i16> @and_constant_mask_undef_4(<4 x i16> %add) {
1066 ; CHECK-LABEL: @and_constant_mask_undef_4(
1067 ; CHECK-NEXT: entry:
1068 ; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison>
1069 ; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
1070 ; CHECK-NEXT: ret <4 x i16> [[AND]]
1073 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
1074 %and = and <4 x i16> %shuffle, <i16 9, i16 20, i16 20, i16 -1>
1078 define <4 x i16> @and_constant_mask_not_undef(<4 x i16> %add) {
1079 ; CHECK-LABEL: @and_constant_mask_not_undef(
1080 ; CHECK-NEXT: entry:
1081 ; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 poison, i16 -1, i16 0, i16 0>
1082 ; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1083 ; CHECK-NEXT: ret <4 x i16> [[AND]]
1086 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1087 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1091 ; OR does not fold to undef for undef operands, we cannot move it
1092 ; across a shuffle with undef masks.
1093 define <4 x i16> @or_constant_mask_undef(<4 x i16> %in) {
1094 ; CHECK-LABEL: @or_constant_mask_undef(
1095 ; CHECK-NEXT: entry:
1096 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1097 ; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
1098 ; CHECK-NEXT: ret <4 x i16> [[OR]]
1101 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1102 %or = or <4 x i16> %shuffle, <i16 -1, i16 -1, i16 0, i16 0>
1106 ; OR does not fold to undef for undef operands, we cannot move it
1107 ; across a shuffle with undef masks.
1108 define <4 x i16> @or_constant_mask_undef_2(<4 x i16> %in) {
1109 ; CHECK-LABEL: @or_constant_mask_undef_2(
1110 ; CHECK-NEXT: entry:
1111 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1112 ; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
1113 ; CHECK-NEXT: ret <4 x i16> [[OR]]
1116 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1117 %or = or <4 x i16> %shuffle, <i16 -1, i16 0, i16 0, i16 -1>
1121 ; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1122 define <4 x i16> @or_constant_mask_undef_3(<4 x i16> %in) {
1123 ; CHECK-LABEL: @or_constant_mask_undef_3(
1124 ; CHECK-NEXT: entry:
1125 ; CHECK-NEXT: ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
1128 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1129 %or = or <4 x i16> %shuffle, <i16 0, i16 -1, i16 -1, i16 0>
1133 ; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1134 define <4 x i16> @or_constant_mask_undef_4(<4 x i16> %in) {
1135 ; CHECK-LABEL: @or_constant_mask_undef_4(
1136 ; CHECK-NEXT: entry:
1137 ; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison>
1138 ; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1139 ; CHECK-NEXT: ret <4 x i16> [[OR]]
1142 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1143 %or = or <4 x i16> %shuffle, <i16 0, i16 99, i16 99, i16 0>
1147 define <4 x i16> @or_constant_mask_not_undef(<4 x i16> %in) {
1148 ; CHECK-LABEL: @or_constant_mask_not_undef(
1149 ; CHECK-NEXT: entry:
1150 ; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 -1, i16 0, i16 0>
1151 ; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1152 ; CHECK-NEXT: ret <4 x i16> [[AND]]
1155 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1156 %and = or <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1160 define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) {
1161 ; CHECK-LABEL: @shl_constant_mask_undef(
1162 ; CHECK-NEXT: entry:
1163 ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 0, i32 undef, i32 1, i32 1>
1164 ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i16> [[SHUFFLE]], <i16 10, i16 3, i16 0, i16 0>
1165 ; CHECK-NEXT: ret <4 x i16> [[SHL]]
1168 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 0, i32 undef, i32 1, i32 1>
1169 %shl = shl <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1173 define <4 x i16> @add_constant_mask_undef(<4 x i16> %in) {
1174 ; CHECK-LABEL: @add_constant_mask_undef(
1175 ; CHECK-NEXT: entry:
1176 ; CHECK-NEXT: [[ADD:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1177 ; CHECK-NEXT: ret <4 x i16> [[ADD]]
1180 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1181 %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1185 define <4 x i16> @add_constant_mask_undef_2(<4 x i16> %in) {
1186 ; CHECK-LABEL: @add_constant_mask_undef_2(
1187 ; CHECK-NEXT: entry:
1188 ; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 3, i16 poison>
1189 ; CHECK-NEXT: [[ADD:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 undef, i32 2, i32 1, i32 1>
1190 ; CHECK-NEXT: ret <4 x i16> [[ADD]]
1193 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 2, i32 1, i32 1>
1194 %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1198 define <4 x i16> @sub_constant_mask_undef(<4 x i16> %in) {
1199 ; CHECK-LABEL: @sub_constant_mask_undef(
1200 ; CHECK-NEXT: entry:
1201 ; CHECK-NEXT: [[SUB:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1202 ; CHECK-NEXT: ret <4 x i16> [[SUB]]
1205 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1206 %sub = sub <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1210 define <4 x i16> @sub_constant_mask_undef_2(<4 x i16> %in) {
1211 ; CHECK-LABEL: @sub_constant_mask_undef_2(
1212 ; CHECK-NEXT: entry:
1213 ; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 -10, i16 poison>
1214 ; CHECK-NEXT: [[SUB:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 undef>
1215 ; CHECK-NEXT: ret <4 x i16> [[SUB]]
1218 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 undef>
1219 %sub = sub <4 x i16> %shuffle, <i16 0, i16 0, i16 10, i16 99>
1223 define <2 x i32> @or_splat_constant(<2 x i32> %x) {
1224 ; CHECK-LABEL: @or_splat_constant(
1225 ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1226 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
1227 ; CHECK-NEXT: ret <2 x i32> [[R]]
1229 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
1230 %r = or <2 x i32> %splat, <i32 42, i32 42>
1234 define <2 x i32> @xor_splat_constant(<2 x i32> %x) {
1235 ; CHECK-LABEL: @xor_splat_constant(
1236 ; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1237 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <2 x i32> zeroinitializer
1238 ; CHECK-NEXT: ret <2 x i32> [[R]]
1240 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer
1241 %r = xor <2 x i32> %splat, <i32 42, i32 42>
1245 define <2 x float> @fadd_splat_constant(<2 x float> %x) {
1246 ; CHECK-LABEL: @fadd_splat_constant(
1247 ; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1248 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1249 ; CHECK-NEXT: ret <2 x float> [[R]]
1251 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1252 %r = fadd <2 x float> %splat, <float 42.0, float 42.0>
1256 define <2 x float> @fsub_splat_constant0(<2 x float> %x) {
1257 ; CHECK-LABEL: @fsub_splat_constant0(
1258 ; CHECK-NEXT: [[TMP1:%.*]] = fsub <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1259 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1260 ; CHECK-NEXT: ret <2 x float> [[R]]
1262 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1263 %r = fsub <2 x float> <float 42.0, float 42.0>, %splat
1267 define <2 x float> @fsub_splat_constant1(<2 x float> %x) {
1268 ; CHECK-LABEL: @fsub_splat_constant1(
1269 ; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float poison>
1270 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1271 ; CHECK-NEXT: ret <2 x float> [[R]]
1273 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1274 %r = fsub <2 x float> %splat, <float 42.0, float 42.0>
1278 define <2 x float> @fneg(<2 x float> %x) {
1279 ; CHECK-LABEL: @fneg(
1280 ; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]
1281 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1282 ; CHECK-NEXT: ret <2 x float> [[R]]
1284 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1285 %r = fsub <2 x float> <float -0.0, float -0.0>, %splat
1289 define <2 x float> @fmul_splat_constant(<2 x float> %x) {
1290 ; CHECK-LABEL: @fmul_splat_constant(
1291 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1292 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1293 ; CHECK-NEXT: ret <2 x float> [[R]]
1295 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1296 %r = fmul <2 x float> %splat, <float 42.0, float 42.0>
1300 define <2 x float> @fdiv_splat_constant0(<2 x float> %x) {
1301 ; CHECK-LABEL: @fdiv_splat_constant0(
1302 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1303 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1304 ; CHECK-NEXT: ret <2 x float> [[R]]
1306 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1307 %r = fdiv <2 x float> <float 42.0, float 42.0>, %splat
1311 define <2 x float> @fdiv_splat_constant1(<2 x float> %x) {
1312 ; CHECK-LABEL: @fdiv_splat_constant1(
1313 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1314 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1315 ; CHECK-NEXT: ret <2 x float> [[R]]
1317 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1318 %r = fdiv <2 x float> %splat, <float 42.0, float 42.0>
1322 define <2 x float> @frem_splat_constant0(<2 x float> %x) {
1323 ; CHECK-LABEL: @frem_splat_constant0(
1324 ; CHECK-NEXT: [[TMP1:%.*]] = frem <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1325 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1326 ; CHECK-NEXT: ret <2 x float> [[R]]
1328 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1329 %r = frem <2 x float> <float 42.0, float 42.0>, %splat
1333 define <2 x float> @frem_splat_constant1(<2 x float> %x) {
1334 ; CHECK-LABEL: @frem_splat_constant1(
1335 ; CHECK-NEXT: [[TMP1:%.*]] = frem <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1336 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> undef, <2 x i32> zeroinitializer
1337 ; CHECK-NEXT: ret <2 x float> [[R]]
1339 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1340 %r = frem <2 x float> %splat, <float 42.0, float 42.0>
1344 ; Equivalent shuffle masks, but only one is a narrowing op.
1346 define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) {
1347 ; CHECK-LABEL: @PR40734(
1348 ; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> <i32 0, i32 1>
1349 ; CHECK-NEXT: [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> undef, <2 x i32> <i32 0, i32 1>
1350 ; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]]
1351 ; CHECK-NEXT: ret <2 x i1> [[R]]
1353 %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> <i32 0, i32 1>
1354 %narrow = shufflevector <4 x i1> %y, <4 x i1> undef, <2 x i32> <i32 0, i32 1>
1355 %r = and <2 x i1> %widen, %narrow
1359 ; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically.
1361 define <7 x i8> @insert_subvector_shuffles(<3 x i8> %x, <3 x i8> %y) {
1362 ; CHECK-LABEL: @insert_subvector_shuffles(
1363 ; CHECK-NEXT: [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> undef, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1364 ; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef>
1365 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <7 x i32> <i32 0, i32 8, i32 1, i32 undef, i32 8, i32 1, i32 9>
1366 ; CHECK-NEXT: ret <7 x i8> [[S3]]
1368 %s1 = shufflevector <3 x i8> %x, <3 x i8> undef, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1369 %s2 = shufflevector <3 x i8> %y, <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef>
1370 %s3 = shufflevector <7 x i8> %s1, <7 x i8> %s2, <7 x i32> <i32 0, i32 8, i32 1, i32 undef, i32 8, i32 1, i32 9>
1374 define <8 x i8> @insert_subvector_shuffles_pow2elts(<2 x i8> %x, <2 x i8> %y) {
1375 ; CHECK-LABEL: @insert_subvector_shuffles_pow2elts(
1376 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <8 x i32> <i32 0, i32 2, i32 1, i32 undef, i32 2, i32 1, i32 3, i32 0>
1377 ; CHECK-NEXT: ret <8 x i8> [[S3]]
1379 %s1 = shufflevector <2 x i8> %x, <2 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1380 %s2 = shufflevector <2 x i8> %y, <2 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1381 %s3 = shufflevector <8 x i8> %s1, <8 x i8> %s2, <8 x i32> <i32 0, i32 8, i32 1, i32 undef, i32 8, i32 1, i32 9, i32 0>
1385 ; The last shuffle may change the vector type.
1386 ; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically.
1388 define <2 x i8> @insert_subvector_shuffles_narrowing(<3 x i8> %x, <3 x i8> %y) {
1389 ; CHECK-LABEL: @insert_subvector_shuffles_narrowing(
1390 ; CHECK-NEXT: [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> undef, <7 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1391 ; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1392 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <2 x i32> <i32 0, i32 8>
1393 ; CHECK-NEXT: ret <2 x i8> [[S3]]
1395 %s1 = shufflevector <3 x i8> %x, <3 x i8> undef, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1396 %s2 = shufflevector <3 x i8> %y, <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef>
1397 %s3 = shufflevector <7 x i8> %s1, <7 x i8> %s2, <2 x i32> <i32 0, i32 8>
1401 define <2 x i8> @insert_subvector_shuffles_narrowing_pow2elts(<4 x i8> %x, <4 x i8> %y) {
1402 ; CHECK-LABEL: @insert_subvector_shuffles_narrowing_pow2elts(
1403 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 4>
1404 ; CHECK-NEXT: ret <2 x i8> [[S3]]
1406 %s1 = shufflevector <4 x i8> %x, <4 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1407 %s2 = shufflevector <4 x i8> %y, <4 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
1408 %s3 = shufflevector <8 x i8> %s1, <8 x i8> %s2, <2 x i32> <i32 0, i32 8>
1412 ; Similar to above, but this reduces to a widen with undefs of 'x'.
1414 define <4 x double> @insert_subvector_shuffles_identity(<2 x double> %x) {
1415 ; CHECK-LABEL: @insert_subvector_shuffles_identity(
1416 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
1417 ; CHECK-NEXT: ret <4 x double> [[S3]]
1419 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef>
1420 %s2 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1421 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>
1422 ret <4 x double> %s3
1425 ; Negative test - not identity with padding (although this could be folded with better analysis).
1427 define <4 x double> @not_insert_subvector_shuffle(<2 x double> %x) {
1428 ; CHECK-LABEL: @not_insert_subvector_shuffle(
1429 ; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 1>
1430 ; CHECK-NEXT: [[S2:%.*]] = shufflevector <2 x double> [[X]], <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1431 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 7, i32 undef>
1432 ; CHECK-NEXT: ret <4 x double> [[S3]]
1434 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 1>
1435 %s2 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1436 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 7, i32 undef>
1437 ret <4 x double> %s3
1440 ; Negative test - operands are not the same size (although this could be partly folded with better analysis).
1442 define <4 x double> @not_insert_subvector_shuffles_with_same_size(<2 x double> %x, <3 x double> %y) {
1443 ; CHECK-LABEL: @not_insert_subvector_shuffles_with_same_size(
1444 ; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef>
1445 ; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x double> [[Y:%.*]], <3 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1446 ; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>
1447 ; CHECK-NEXT: ret <4 x double> [[S3]]
1449 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef>
1450 %s2 = shufflevector <3 x double> %y, <3 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1451 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>
1452 ret <4 x double> %s3
1455 ; Demanded vector elements may not be able to simplify a shuffle mask
1456 ; before we try to narrow it. This used to crash.
1458 define <4 x float> @insert_subvector_crash_invalid_mask_elt(<2 x float> %x, <4 x float>* %p) {
1459 ; CHECK-LABEL: @insert_subvector_crash_invalid_mask_elt(
1460 ; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
1461 ; CHECK-NEXT: [[I:%.*]] = shufflevector <2 x float> [[X]], <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
1462 ; CHECK-NEXT: store <4 x float> [[I]], <4 x float>* [[P:%.*]], align 16
1463 ; CHECK-NEXT: ret <4 x float> [[WIDEN]]
1465 %widen = shufflevector <2 x float> %x, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
1466 %ext2 = extractelement <2 x float> %x, i32 0
1467 %I = insertelement <4 x float> %widen, float %ext2, i16 0
1468 store <4 x float> %I, <4 x float>* %p
1469 ret <4 x float> %widen
1472 define <4 x i32> @splat_assoc_add(<4 x i32> %x, <4 x i32> %y) {
1473 ; CHECK-LABEL: @splat_assoc_add(
1474 ; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 317426, i32 poison, i32 poison, i32 poison>
1475 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1476 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1477 ; CHECK-NEXT: ret <4 x i32> [[R]]
1479 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
1480 %a = add <4 x i32> %y, <i32 317426, i32 317426, i32 317426, i32 317426>
1481 %r = add <4 x i32> %splatx, %a
1485 define <vscale x 4 x i32> @vsplat_assoc_add(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
1486 ; CHECK-LABEL: @vsplat_assoc_add(
1487 ; CHECK-NEXT: [[TMP1:%.*]] = add <vscale x 4 x i32> [[X:%.*]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> undef, i32 317426, i32 0), <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer)
1488 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
1489 ; CHECK-NEXT: [[R:%.*]] = add <vscale x 4 x i32> [[TMP2]], [[Y:%.*]]
1490 ; CHECK-NEXT: ret <vscale x 4 x i32> [[R]]
1493 %splatx = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer
1494 %a = add <vscale x 4 x i32> %y, shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> undef, i32 317426, i32 0), <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer)
1495 %r = add <vscale x 4 x i32> %splatx, %a
1496 ret <vscale x 4 x i32> %r
1499 ; Undefs in splat mask are replaced with defined splat index
1501 define <4 x i32> @splat_assoc_add_undef_mask_elts(<4 x i32> %x, <4 x i32> %y) {
1502 ; CHECK-LABEL: @splat_assoc_add_undef_mask_elts(
1503 ; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison>
1504 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1505 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1506 ; CHECK-NEXT: ret <4 x i32> [[R]]
1508 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 undef, i32 undef>
1509 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1510 %r = add <4 x i32> %splatx, %a
1514 ; Undefs in splat mask are replaced with defined splat index
1516 define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) {
1517 ; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index(
1518 ; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison>
1519 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1520 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1521 ; CHECK-NEXT: ret <4 x i32> [[R]]
1523 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1524 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1525 %r = add <4 x i32> %splatx, %a
1529 define <4 x i32> @splat_assoc_add_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1530 ; CHECK-LABEL: @splat_assoc_add_undef_constant_elts(
1531 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
1532 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1533 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1534 ; CHECK-NEXT: ret <4 x i32> [[R]]
1536 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
1537 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1538 %r = add <4 x i32> %splatx, %a
1542 define <4 x i32> @splat_assoc_add_undef_constant_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) {
1543 ; CHECK-LABEL: @splat_assoc_add_undef_constant_elt_at_splat_index(
1544 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
1545 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42>
1546 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1547 ; CHECK-NEXT: ret <4 x i32> [[R]]
1549 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
1550 %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42>
1551 %r = add <4 x i32> %splatx, %a
1555 define <4 x i32> @splat_assoc_add_undef_mask_elts_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1556 ; CHECK-LABEL: @splat_assoc_add_undef_mask_elts_undef_constant_elts(
1557 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 0, i32 undef, i32 0, i32 undef>
1558 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1559 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1560 ; CHECK-NEXT: ret <4 x i32> [[R]]
1562 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 undef, i32 0, i32 undef>
1563 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1564 %r = add <4 x i32> %splatx, %a
1568 define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1569 ; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts(
1570 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1571 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1572 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1573 ; CHECK-NEXT: ret <4 x i32> [[R]]
1575 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1576 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1577 %r = add <4 x i32> %splatx, %a
1581 define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) {
1582 ; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elt_at_splat_index(
1583 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1584 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42>
1585 ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1586 ; CHECK-NEXT: ret <4 x i32> [[R]]
1588 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1589 %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42>
1590 %r = add <4 x i32> %splatx, %a
1594 ; Non-zero splat index; commute operands; FMF intersect
1596 define <2 x float> @splat_assoc_fmul(<2 x float> %x, <2 x float> %y) {
1597 ; CHECK-LABEL: @splat_assoc_fmul(
1598 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], <float poison, float 3.000000e+00>
1599 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 1>
1600 ; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP2]], [[Y:%.*]]
1601 ; CHECK-NEXT: ret <2 x float> [[R]]
1603 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> <i32 1, i32 1>
1604 %a = fmul reassoc nsz <2 x float> %y, <float 3.0, float 3.0>
1605 %r = fmul reassoc nsz nnan <2 x float> %a, %splatx
1609 ; Two splat shuffles; drop poison-generating flags
1611 define <3 x i8> @splat_assoc_mul(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1612 ; CHECK-LABEL: @splat_assoc_mul(
1613 ; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[Z:%.*]], [[X:%.*]]
1614 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1615 ; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1616 ; CHECK-NEXT: ret <3 x i8> [[R]]
1618 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1619 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1620 %a = mul nsw <3 x i8> %y, %splatz
1621 %r = mul <3 x i8> %a, %splatx
1625 define <3 x i8> @splat_assoc_mul_undef_elt1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1626 ; CHECK-LABEL: @splat_assoc_mul_undef_elt1(
1627 ; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[Z:%.*]], [[X:%.*]]
1628 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1629 ; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1630 ; CHECK-NEXT: ret <3 x i8> [[R]]
1632 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 undef, i32 2, i32 2>
1633 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1634 %a = mul nsw <3 x i8> %y, %splatz
1635 %r = mul nsw nuw <3 x i8> %a, %splatx
1639 define <3 x i8> @splat_assoc_mul_undef_elt2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1640 ; CHECK-LABEL: @splat_assoc_mul_undef_elt2(
1641 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1642 ; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> undef, <3 x i32> <i32 undef, i32 2, i32 2>
1643 ; CHECK-NEXT: [[A:%.*]] = mul nsw <3 x i8> [[SPLATZ]], [[Y:%.*]]
1644 ; CHECK-NEXT: [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]]
1645 ; CHECK-NEXT: ret <3 x i8> [[R]]
1647 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1648 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 undef, i32 2, i32 2>
1649 %a = mul nsw <3 x i8> %y, %splatz
1650 %r = mul nsw nuw <3 x i8> %a, %splatx
1654 define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1655 ; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index1(
1656 ; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[Z:%.*]], [[X:%.*]]
1657 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1658 ; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1659 ; CHECK-NEXT: ret <3 x i8> [[R]]
1661 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 undef>
1662 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1663 %a = mul nsw <3 x i8> %y, %splatz
1664 %r = mul nsw nuw <3 x i8> %a, %splatx
1668 define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1669 ; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index2(
1670 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1671 ; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 undef>
1672 ; CHECK-NEXT: [[A:%.*]] = mul nsw <3 x i8> [[SPLATZ]], [[Y:%.*]]
1673 ; CHECK-NEXT: [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]]
1674 ; CHECK-NEXT: ret <3 x i8> [[R]]
1676 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1677 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 undef>
1678 %a = mul nsw <3 x i8> %y, %splatz
1679 %r = mul nsw nuw <3 x i8> %a, %splatx
1683 ; Negative test - mismatched splat elements
1685 define <3 x i8> @splat_assoc_or(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1686 ; CHECK-LABEL: @splat_assoc_or(
1687 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> undef, <3 x i32> <i32 1, i32 1, i32 1>
1688 ; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1689 ; CHECK-NEXT: [[A:%.*]] = or <3 x i8> [[SPLATZ]], [[Y:%.*]]
1690 ; CHECK-NEXT: [[R:%.*]] = or <3 x i8> [[A]], [[SPLATX]]
1691 ; CHECK-NEXT: ret <3 x i8> [[R]]
1693 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 1, i32 1, i32 1>
1694 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2>
1695 %a = or <3 x i8> %y, %splatz
1696 %r = or <3 x i8> %a, %splatx
1700 ; Negative test - not associative
1702 define <2 x float> @splat_assoc_fdiv(<2 x float> %x, <2 x float> %y) {
1703 ; CHECK-LABEL: @splat_assoc_fdiv(
1704 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> undef, <2 x i32> zeroinitializer
1705 ; CHECK-NEXT: [[A:%.*]] = fdiv reassoc nsz <2 x float> [[Y:%.*]], <float 3.000000e+00, float 3.000000e+00>
1706 ; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz <2 x float> [[A]], [[SPLATX]]
1707 ; CHECK-NEXT: ret <2 x float> [[R]]
1709 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
1710 %a = fdiv reassoc nsz <2 x float> %y, <float 3.0, float 3.0>
1711 %r = fdiv reassoc nsz <2 x float> %a, %splatx
1715 ; Negative test - extra use
1717 define <2 x float> @splat_assoc_fadd(<2 x float> %x, <2 x float> %y) {
1718 ; CHECK-LABEL: @splat_assoc_fadd(
1719 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> undef, <2 x i32> <i32 1, i32 1>
1720 ; CHECK-NEXT: [[A:%.*]] = fadd fast <2 x float> [[Y:%.*]], <float 3.000000e+00, float 3.000000e+00>
1721 ; CHECK-NEXT: call void @use(<2 x float> [[A]])
1722 ; CHECK-NEXT: [[R:%.*]] = fadd fast <2 x float> [[A]], [[SPLATX]]
1723 ; CHECK-NEXT: ret <2 x float> [[R]]
1725 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> <i32 1, i32 1>
1726 %a = fadd fast <2 x float> %y, <float 3.0, float 3.0>
1727 call void @use(<2 x float> %a)
1728 %r = fadd fast <2 x float> %a, %splatx
1732 ; Negative test - narrowing splat
1734 define <3 x i32> @splat_assoc_and(<4 x i32> %x, <3 x i32> %y) {
1735 ; CHECK-LABEL: @splat_assoc_and(
1736 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <3 x i32> zeroinitializer
1737 ; CHECK-NEXT: [[A:%.*]] = and <3 x i32> [[Y:%.*]], <i32 42, i32 42, i32 42>
1738 ; CHECK-NEXT: [[R:%.*]] = and <3 x i32> [[SPLATX]], [[A]]
1739 ; CHECK-NEXT: ret <3 x i32> [[R]]
1741 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <3 x i32> zeroinitializer
1742 %a = and <3 x i32> %y, <i32 42, i32 42, i32 42>
1743 %r = and <3 x i32> %splatx, %a
1747 ; Negative test - widening splat
1749 define <5 x i32> @splat_assoc_xor(<4 x i32> %x, <5 x i32> %y) {
1750 ; CHECK-LABEL: @splat_assoc_xor(
1751 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <5 x i32> zeroinitializer
1752 ; CHECK-NEXT: [[TMP1:%.*]] = xor <5 x i32> [[SPLATX]], [[Y:%.*]]
1753 ; CHECK-NEXT: [[R:%.*]] = xor <5 x i32> [[TMP1]], <i32 42, i32 42, i32 42, i32 42, i32 42>
1754 ; CHECK-NEXT: ret <5 x i32> [[R]]
1756 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <5 x i32> zeroinitializer
1757 %a = xor <5 x i32> %y, <i32 42, i32 42, i32 42, i32 42, i32 42>
1758 %r = xor <5 x i32> %splatx, %a
1762 ; Negative test - opcode mismatch
1764 define <4 x i32> @splat_assoc_add_mul(<4 x i32> %x, <4 x i32> %y) {
1765 ; CHECK-LABEL: @splat_assoc_add_mul(
1766 ; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
1767 ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 42, i32 42, i32 42>
1768 ; CHECK-NEXT: [[R:%.*]] = mul <4 x i32> [[SPLATX]], [[A]]
1769 ; CHECK-NEXT: ret <4 x i32> [[R]]
1771 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
1772 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1773 %r = mul <4 x i32> %splatx, %a
1778 ; Do not crash on constant expressions.
1780 define <4 x i32> @PR46872(<4 x i32> %x) {
1781 ; CHECK-LABEL: @PR46872(
1782 ; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 1, i32 1>
1783 ; CHECK-NEXT: [[A:%.*]] = and <4 x i32> [[S]], bitcast (<2 x i64> <i64 ptrtoint (<4 x i32> (<4 x i32>)* @PR46872 to i64), i64 ptrtoint (<4 x i32> (<4 x i32>)* @PR46872 to i64)> to <4 x i32>)
1784 ; CHECK-NEXT: ret <4 x i32> [[A]]
1786 %s = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 1, i32 1>
1787 %a = and <4 x i32> %s, bitcast (<2 x i64> <i64 ptrtoint (<4 x i32> (<4 x i32>)* @PR46872 to i64), i64 ptrtoint (<4 x i32> (<4 x i32>)* @PR46872 to i64)> to <4 x i32>)