[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / vec_shuffle.ll
blob9cee1f3ad73e775a707178c5f6ebb6aecde60e0d
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) {
5 ; CHECK-LABEL: @test1(
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>
9   ret <4 x float> %v2
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>
17   ret <4 x float> %v2
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
27   ret float %E
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
37   ret i32 %r
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
47   ret i32 %r
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
59   ret float %r
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
72   ret float %r
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 >
82   ret <4 x float> %r
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
98   ret <4 x float> %t134
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 >
110   ret <4 x i8> %t9
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 >
125   ret <4 x i8> %t9
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>
137   ret <4 x i8> %t9
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
148   ret <4 x i32> %t7
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>
161   ret <8 x i8> %t3
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>
173   ret <8 x i8> %t3
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>
185   ret <8 x i8> %t3
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>
241   ret <2 x i8> %D
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>
258   ret <3 x i32> %ext
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>
275   ret <3 x i32> %ext
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>
289   ret <3 x i8> %widen
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>
299   ret <2 x i8> %B
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>
311   ret <2 x i8> %C
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>
330   ret void
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
345   ret <4 x float> %t4
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
359   ret <4 x float> %t5
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>
369   ret <1 x i32> %t2
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>
379   ret <4 x i8> %t2
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
402   ret <4 x i32> %r
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)
421   ret <2 x float> %r
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)
436   ret <2 x float> %r
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)
455   ret <2 x float> %r
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
467   ret <4 x i32> %r
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
479   ret <4 x i32> %r
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
491   ret <4 x i32> %r
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
503   ret <4 x float> %r
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>
514   ret <4 x i32> %r
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
525   ret <4 x i32> %r
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)
540   ret <2 x float> %r
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
553   ret <4 x i32> %r
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
566   ret <4 x i32> %r
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>
579   ret <2 x float> %r
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>
592   ret <4 x i8> %r
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>
605   ret <4 x i8> %r
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>
618   ret <4 x i8> %r
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>
631   ret <4 x i8> %r
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
645   ret <4 x i16> %bo
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>
659   ret <4 x i16> %bo
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>
673   ret <4 x i16> %bo
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>
687   ret <4 x i16> %bo
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>
698   ret <4 x i32> %r
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>
710   ret <4 x i32> %s2
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
724   ret <2 x i32> %mul
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
736   ret <4 x i16> %mul
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
759   ret i32 %rv
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
764 ; on div-by-zero.
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>
796   ret <2 x 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>
807   ret <2 x i32> %r
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>
821   ret <2 x i32> %r
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
832   ret <2 x i32> %r
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>
843   ret <2 x i32> %r
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>
854   ret <2 x i32> %r
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
865   ret <2 x i32> %r
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>
876   ret <2 x i32> %r
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
887   ret <2 x i32> %r
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>
898   ret <2 x i32> %r
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
909   ret <2 x i32> %r
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>
920   ret <2 x i32> %r
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
931   ret <2 x i32> %r
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>
942   ret <2 x i32> %r
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
953   ret <2 x i32> %r
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>
964   ret <2 x i32> %r
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
975   ret <2 x i32> %r
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>
986   ret <2 x i32> %r
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
997   ret <2 x i32> %r
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>
1008   ret <2 x i32> %r
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>
1019   ret <2 x i32> %r
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]]
1031 entry:
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>
1034   ret <4 x i16> %and
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]]
1046 entry:
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>
1049   ret <4 x i16> %and
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>
1058 entry:
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>
1061   ret <4 x i16> %and
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]]
1072 entry:
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>
1075   ret <4 x i16> %and
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]]
1085 entry:
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>
1088   ret <4 x i16> %and
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]]
1100 entry:
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>
1103   ret <4 x i16> %or
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]]
1115 entry:
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>
1118   ret <4 x i16> %or
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>
1127 entry:
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>
1130   ret <4 x i16> %or
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]]
1141 entry:
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>
1144   ret <4 x i16> %or
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]]
1154 entry:
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>
1157   ret <4 x i16> %and
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]]
1167 entry:
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>
1170   ret <4 x i16> %shl
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]]
1179 entry:
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>
1182   ret <4 x i16> %add
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]]
1192 entry:
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>
1195   ret <4 x i16> %add
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]]
1204 entry:
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>
1207   ret <4 x i16> %sub
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]]
1217 entry:
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>
1220   ret <4 x i16> %sub
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>
1231   ret <2 x i32> %r
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>
1242   ret <2 x i32> %r
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>
1253   ret <2 x float> %r
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
1264   ret <2 x float> %r
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>
1275   ret <2 x float> %r
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
1286   ret <2 x float> %r
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>
1297   ret <2 x float> %r
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
1308   ret <2 x float> %r
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>
1319   ret <2 x float> %r
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
1330   ret <2 x float> %r
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>
1341   ret <2 x float> %r
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
1356   ret <2 x i1> %r
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>
1371   ret <7 x i8> %s3
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>
1382   ret <8 x i8> %s3
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>
1398   ret <2 x i8> %s3
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>
1409   ret <2 x i8> %s3
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
1482   ret <4 x i32> %r
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
1511   ret <4 x i32> %r
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
1526   ret <4 x i32> %r
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
1539   ret <4 x i32> %r
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
1552   ret <4 x i32> %r
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
1565   ret <4 x i32> %r
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
1578   ret <4 x i32> %r
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
1591   ret <4 x i32> %r
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
1606   ret <2 x float> %r
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
1622   ret <3 x i8> %r
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
1636   ret <3 x i8> %r
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
1651   ret <3 x i8> %r
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
1665   ret <3 x i8> %r
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
1680   ret <3 x i8> %r
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
1697   ret <3 x i8> %r
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
1712   ret <2 x float> %r
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
1729   ret <2 x float> %r
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
1744   ret <3 x i32> %r
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
1759   ret <5 x i32> %r
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
1774   ret <4 x i32> %r
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>)
1788   ret <4 x i32> %a