xref: /llvm-project/llvm/test/Transforms/InstCombine/vec_shuffle-inseltpoison.ll (revision 56c091ea7106507b36015297ee9005c9d5fab0bf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define <4 x float> @test1(<4 x float> %v1) {
5; CHECK-LABEL: @test1(
6; CHECK-NEXT:    ret <4 x float> [[V1:%.*]]
7;
8  %v2 = shufflevector <4 x float> %v1, <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
9  ret <4 x float> %v2
10}
11
12define <4 x float> @test2(<4 x float> %v1) {
13; CHECK-LABEL: @test2(
14; CHECK-NEXT:    ret <4 x float> [[V1:%.*]]
15;
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
18}
19
20define float @test3(<4 x float> %A, <4 x float> %B, float %f) {
21; CHECK-LABEL: @test3(
22; CHECK-NEXT:    ret float [[F:%.*]]
23;
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
28}
29
30define i32 @test4(<4 x i32> %X) {
31; CHECK-LABEL: @test4(
32; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i64 0
33; CHECK-NEXT:    ret i32 [[R]]
34;
35  %t = shufflevector <4 x i32> %X, <4 x i32> poison, <4 x i32> zeroinitializer
36  %r = extractelement <4 x i32> %t, i32 0
37  ret i32 %r
38}
39
40define i32 @test5(<4 x i32> %X) {
41; CHECK-LABEL: @test5(
42; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i64 3
43; CHECK-NEXT:    ret i32 [[R]]
44;
45  %t = shufflevector <4 x i32> %X, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 undef, i32 undef>
46  %r = extractelement <4 x i32> %t, i32 0
47  ret i32 %r
48}
49
50define float @test6(<4 x float> %X) {
51; CHECK-LABEL: @test6(
52; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x float> [[X:%.*]], i64 0
53; CHECK-NEXT:    ret float [[R]]
54;
55  %X1 = bitcast <4 x float> %X to <4 x i32>
56  %t = shufflevector <4 x i32> %X1, <4 x i32> poison, <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
60}
61
62define 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> poison, <vscale x 4 x i32> zeroinitializer
65; CHECK-NEXT:    [[R:%.*]] = extractelement <vscale x 4 x float> [[T2]], i64 0
66; CHECK-NEXT:    ret float [[R]]
67;
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> poison, <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
73}
74
75
76define <4 x float> @test7(<4 x float> %x) {
77; CHECK-LABEL: @test7(
78; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
79; CHECK-NEXT:    ret <4 x float> [[R]]
80;
81  %r = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> < i32 0, i32 1, i32 6, i32 7 >
82  ret <4 x float> %r
83}
84
85; This should turn into a single shuffle.
86define <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 poison, i32 3, i32 4>
89; CHECK-NEXT:    ret <4 x float> [[T134]]
90;
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> poison, float %t4, i32 0
95  %t130 = insertelement <4 x float> %t128, float poison, 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
99}
100
101; This shouldn't turn into a single shuffle
102define <4 x float> @test8_undef(<4 x float> %x, <4 x float> %y) {
103; CHECK-LABEL: @test8_undef(
104; CHECK-NEXT:    [[T132:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> <float poison, float undef, float poison, float poison>, <4 x i32> <i32 1, i32 5, i32 3, i32 poison>
105; CHECK-NEXT:    [[T134:%.*]] = shufflevector <4 x float> [[T132]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 4>
106; CHECK-NEXT:    ret <4 x float> [[T134]]
107;
108  %t4 = extractelement <4 x float> %x, i32 1
109  %t2 = extractelement <4 x float> %x, i32 3
110  %t1 = extractelement <4 x float> %y, i32 0
111  %t128 = insertelement <4 x float> poison, float %t4, i32 0
112  %t130 = insertelement <4 x float> %t128, float undef, i32 1
113  %t132 = insertelement <4 x float> %t130, float %t2, i32 2
114  %t134 = insertelement <4 x float> %t132, float %t1, i32 3
115  ret <4 x float> %t134
116}
117
118; Test fold of two shuffles where the first shuffle vectors inputs are a
119; different length then the second.
120define <4 x i8> @test9(<16 x i8> %t6) {
121; CHECK-LABEL: @test9(
122; CHECK-NEXT:    [[T9:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <4 x i32> <i32 13, i32 9, i32 4, i32 13>
123; CHECK-NEXT:    ret <4 x i8> [[T9]]
124;
125  %t7 = shufflevector <16 x i8> %t6, <16 x i8> poison, <4 x i32> < i32 13, i32 9, i32 4, i32 13 >
126  %t9 = shufflevector <4 x i8> %t7, <4 x i8> poison, <4 x i32> < i32 3, i32 1, i32 2, i32 0 >
127  ret <4 x i8> %t9
128}
129
130; Same as test9, but make sure that "undef" mask values are not confused with
131; mask values of 2*N, where N is the mask length.  These shuffles should not
132; be folded (because [8,9,4,8] may not be a mask supported by the target).
133
134define <4 x i8> @test9a(<16 x i8> %t6) {
135; CHECK-LABEL: @test9a(
136; CHECK-NEXT:    [[T7:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <4 x i32> <i32 poison, i32 9, i32 4, i32 8>
137; CHECK-NEXT:    [[T9:%.*]] = shufflevector <4 x i8> [[T7]], <4 x i8> poison, <4 x i32> <i32 3, i32 1, i32 2, i32 poison>
138; CHECK-NEXT:    ret <4 x i8> [[T9]]
139;
140  %t7 = shufflevector <16 x i8> %t6, <16 x i8> poison, <4 x i32> < i32 undef, i32 9, i32 4, i32 8 >
141  %t9 = shufflevector <4 x i8> %t7, <4 x i8> poison, <4 x i32> < i32 3, i32 1, i32 2, i32 0 >
142  ret <4 x i8> %t9
143}
144
145; Test fold of two shuffles where the first shuffle vectors inputs are a
146; different length then the second.
147define <4 x i8> @test9b(<4 x i8> %t6, <4 x i8> %t7) {
148; CHECK-LABEL: @test9b(
149; CHECK-NEXT:    [[T9:%.*]] = shufflevector <4 x i8> [[T6:%.*]], <4 x i8> [[T7:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
150; CHECK-NEXT:    ret <4 x i8> [[T9]]
151;
152  %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>
153  %t9 = shufflevector <8 x i8> %t1, <8 x i8> poison, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
154  ret <4 x i8> %t9
155}
156
157; Redundant vector splats should be removed.  Radar 8597790.
158define <4 x i32> @test10(<4 x i32> %t5) {
159; CHECK-LABEL: @test10(
160; CHECK-NEXT:    [[T7:%.*]] = shufflevector <4 x i32> [[T5:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
161; CHECK-NEXT:    ret <4 x i32> [[T7]]
162;
163  %t6 = shufflevector <4 x i32> %t5, <4 x i32> poison, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
164  %t7 = shufflevector <4 x i32> %t6, <4 x i32> poison, <4 x i32> zeroinitializer
165  ret <4 x i32> %t7
166}
167
168; Test fold of two shuffles where the two shufflevector inputs's op1 are the same.
169
170define <8 x i8> @test11(<16 x i8> %t6) {
171; CHECK-LABEL: @test11(
172; CHECK-NEXT:    [[T3:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
173; CHECK-NEXT:    ret <8 x i8> [[T3]]
174;
175  %t1 = shufflevector <16 x i8> %t6, <16 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
176  %t2 = shufflevector <16 x i8> %t6, <16 x i8> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
177  %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>
178  ret <8 x i8> %t3
179}
180
181; Test fold of two shuffles where the first shufflevector's inputs are the same as the second.
182
183define <8 x i8> @test12(<8 x i8> %t6, <8 x i8> %t2) {
184; CHECK-LABEL: @test12(
185; 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>
186; CHECK-NEXT:    ret <8 x i8> [[T3]]
187;
188  %t1 = shufflevector <8 x i8> %t6, <8 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7>
189  %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>
190  ret <8 x i8> %t3
191}
192
193; Test fold of two shuffles where the first shufflevector's inputs are the same as the second.
194
195define <8 x i8> @test12a(<8 x i8> %t6, <8 x i8> %t2) {
196; CHECK-LABEL: @test12a(
197; 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>
198; CHECK-NEXT:    ret <8 x i8> [[T3]]
199;
200  %t1 = shufflevector <8 x i8> %t6, <8 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7>
201  %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>
202  ret <8 x i8> %t3
203}
204
205; The mask length of the 1st shuffle can be reduced to eliminate the 2nd shuffle.
206
207define <2 x i8> @extract_subvector_of_shuffle(<2 x i8> %x, <2 x i8> %y) {
208; CHECK-LABEL: @extract_subvector_of_shuffle(
209; CHECK-NEXT:    [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 2>
210; CHECK-NEXT:    ret <2 x i8> [[EXTRACT_SUBV]]
211;
212  %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <3 x i32> <i32 0, i32 2, i32 0>
213  %extract_subv = shufflevector <3 x i8> %shuf, <3 x i8> poison, <2 x i32> <i32 0, i32 1>
214  ret <2 x i8> %extract_subv
215}
216
217; Undef elements in either mask are ok. Undefs from the 2nd shuffle mask should propagate to the new shuffle.
218; The type of the inputs does not have to match the output type.
219
220define <4 x i8> @extract_subvector_of_shuffle_undefs_types(<2 x i8> %x, <2 x i8> %y) {
221; CHECK-LABEL: @extract_subvector_of_shuffle_undefs_types(
222; CHECK-NEXT:    [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <4 x i32> <i32 poison, i32 2, i32 0, i32 poison>
223; CHECK-NEXT:    ret <4 x i8> [[EXTRACT_SUBV]]
224;
225  %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0>
226  %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
227  ret <4 x i8> %extract_subv
228}
229
230; Extra uses are not ok - we only do the transform when we can eliminate an instruction.
231
232declare void @use_v5i8(<5 x i8>)
233
234define <4 x i8> @extract_subvector_of_shuffle_extra_use(<2 x i8> %x, <2 x i8> %y) {
235; CHECK-LABEL: @extract_subvector_of_shuffle_extra_use(
236; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <5 x i32> <i32 poison, i32 2, i32 0, i32 1, i32 0>
237; CHECK-NEXT:    call void @use_v5i8(<5 x i8> [[SHUF]])
238; CHECK-NEXT:    [[EXTRACT_SUBV:%.*]] = shufflevector <5 x i8> [[SHUF]], <5 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
239; CHECK-NEXT:    ret <4 x i8> [[EXTRACT_SUBV]]
240;
241  %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0>
242  call void @use_v5i8(<5 x i8> %shuf)
243  %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
244  ret <4 x i8> %extract_subv
245}
246
247define <2 x i8> @test13a(i8 %x1, i8 %x2) {
248; CHECK-LABEL: @test13a(
249; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[X2:%.*]], i64 0
250; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X1:%.*]], i64 1
251; CHECK-NEXT:    [[D:%.*]] = add <2 x i8> [[TMP2]], <i8 7, i8 5>
252; CHECK-NEXT:    ret <2 x i8> [[D]]
253;
254  %A = insertelement <2 x i8> poison, i8 %x1, i32 0
255  %B = insertelement <2 x i8> %A, i8 %x2, i32 1
256  %C = add <2 x i8> %B, <i8 5, i8 7>
257  %D = shufflevector <2 x i8> %C, <2 x i8> poison, <2 x i32> <i32 1, i32 0>
258  ret <2 x i8> %D
259}
260
261; Increasing length of vector ops is not a good canonicalization.
262
263define <3 x i32> @add_wider(i32 %y, i32 %z) {
264; CHECK-LABEL: @add_wider(
265; CHECK-NEXT:    [[I0:%.*]] = insertelement <2 x i32> poison, i32 [[Y:%.*]], i64 0
266; CHECK-NEXT:    [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i64 1
267; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[I1]], splat (i32 255)
268; CHECK-NEXT:    [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 poison>
269; CHECK-NEXT:    ret <3 x i32> [[EXT]]
270;
271  %i0 = insertelement <2 x i32> poison, i32 %y, i32 0
272  %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1
273  %a = add <2 x i32> %i1, <i32 255, i32 255>
274  %ext = shufflevector <2 x i32> %a, <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 undef>
275  ret <3 x i32> %ext
276}
277
278; Increasing length of vector ops must be safe from illegal undef propagation.
279
280define <3 x i32> @div_wider(i32 %y, i32 %z) {
281; CHECK-LABEL: @div_wider(
282; CHECK-NEXT:    [[I0:%.*]] = insertelement <2 x i32> poison, i32 [[Y:%.*]], i64 0
283; CHECK-NEXT:    [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i64 1
284; CHECK-NEXT:    [[A:%.*]] = sdiv <2 x i32> [[I1]], splat (i32 255)
285; CHECK-NEXT:    [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 poison>
286; CHECK-NEXT:    ret <3 x i32> [[EXT]]
287;
288  %i0 = insertelement <2 x i32> poison, i32 %y, i32 0
289  %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1
290  %a = sdiv <2 x i32> %i1, <i32 255, i32 255>
291  %ext = shufflevector <2 x i32> %a, <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 undef>
292  ret <3 x i32> %ext
293}
294
295; Increasing length of insertelements (no math ops) is a good canonicalization.
296
297define <3 x i8> @fold_inselts_with_widening_shuffle(i8 %x, i8 %y) {
298; CHECK-LABEL: @fold_inselts_with_widening_shuffle(
299; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <3 x i8> poison, i8 [[X:%.*]], i64 0
300; CHECK-NEXT:    [[WIDEN:%.*]] = insertelement <3 x i8> [[TMP1]], i8 [[Y:%.*]], i64 1
301; CHECK-NEXT:    ret <3 x i8> [[WIDEN]]
302;
303  %ins0 = insertelement <2 x i8> poison, i8 %x, i32 0
304  %ins1 = insertelement <2 x i8> %ins0, i8 %y, i32 1
305  %widen = shufflevector <2 x i8> %ins1, <2 x i8> poison, <3 x i32> <i32 0, i32 1, i32 undef>
306  ret <3 x i8> %widen
307}
308
309define <2 x i8> @test13b(i8 %x) {
310; CHECK-LABEL: @test13b(
311; CHECK-NEXT:    [[B:%.*]] = insertelement <2 x i8> poison, i8 [[X:%.*]], i64 1
312; CHECK-NEXT:    ret <2 x i8> [[B]]
313;
314  %A = insertelement <2 x i8> poison, i8 %x, i32 0
315  %B = shufflevector <2 x i8> %A, <2 x i8> poison, <2 x i32> <i32 undef, i32 0>
316  ret <2 x i8> %B
317}
318
319define <2 x i8> @test13c(i8 %x1, i8 %x2) {
320; CHECK-LABEL: @test13c(
321; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[X1:%.*]], i64 0
322; CHECK-NEXT:    [[C:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X2:%.*]], i64 1
323; CHECK-NEXT:    ret <2 x i8> [[C]]
324;
325  %A = insertelement <4 x i8> poison, i8 %x1, i32 0
326  %B = insertelement <4 x i8> %A, i8 %x2, i32 2
327  %C = shufflevector <4 x i8> %B, <4 x i8> poison, <2 x i32> <i32 0, i32 2>
328  ret <2 x i8> %C
329}
330
331define void @test14(i16 %conv10) {
332; CHECK-LABEL: @test14(
333; CHECK-NEXT:    store <4 x i16> <i16 poison, i16 poison, i16 poison, i16 23>, ptr undef, align 8
334; CHECK-NEXT:    ret void
335;
336  %t = alloca <4 x i16>, align 8
337  %vecinit6 = insertelement <4 x i16> poison, i16 23, i32 3
338  store <4 x i16> %vecinit6, ptr undef
339  %t1 = load <4 x i16>, ptr undef
340  %vecinit11 = insertelement <4 x i16> poison, i16 %conv10, i32 3
341  %div = udiv <4 x i16> %t1, %vecinit11
342  store <4 x i16> %div, ptr %t
343  %t4 = load <4 x i16>, ptr %t
344  %t5 = shufflevector <4 x i16> %t4, <4 x i16> poison, <2 x i32> <i32 2, i32 0>
345  %cmp = icmp ule <2 x i16> %t5, undef
346  %sext = sext <2 x i1> %cmp to <2 x i16>
347  ret void
348}
349
350; Check that sequences of insert/extract element are
351; collapsed into valid shuffle instruction with correct shuffle indexes.
352
353define <4 x float> @test15a(<4 x float> %LHS, <4 x float> %RHS) {
354; CHECK-LABEL: @test15a(
355; CHECK-NEXT:    [[T4:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 0, i32 6, i32 6>
356; CHECK-NEXT:    ret <4 x float> [[T4]]
357;
358  %t1 = extractelement <4 x float> %LHS, i32 0
359  %t2 = insertelement <4 x float> %RHS, float %t1, i32 1
360  %t3 = extractelement <4 x float> %RHS, i32 2
361  %t4 = insertelement <4 x float> %t2, float %t3, i32 3
362  ret <4 x float> %t4
363}
364
365define <4 x float> @test15b(<4 x float> %LHS, <4 x float> %RHS) {
366; CHECK-LABEL: @test15b(
367; CHECK-NEXT:    [[T5:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 3, i32 6, i32 6>
368; CHECK-NEXT:    ret <4 x float> [[T5]]
369;
370  %t0 = extractelement <4 x float> %LHS, i32 3
371  %t1 = insertelement <4 x float> %RHS, float %t0, i32 0
372  %t2 = extractelement <4 x float> %t1, i32 0
373  %t3 = insertelement <4 x float> %RHS, float %t2, i32 1
374  %t4 = extractelement <4 x float> %RHS, i32 2
375  %t5 = insertelement <4 x float> %t3, float %t4, i32 3
376  ret <4 x float> %t5
377}
378
379define <1 x i32> @test16a(i32 %ele) {
380; CHECK-LABEL: @test16a(
381; CHECK-NEXT:    ret <1 x i32> splat (i32 2)
382;
383  %t0 = insertelement <2 x i32> <i32 1, i32 undef>, i32 %ele, i32 1
384  %t1 = shl <2 x i32> %t0, <i32 1, i32 1>
385  %t2 = shufflevector <2 x i32> %t1, <2 x i32> poison, <1 x i32> <i32 0>
386  ret <1 x i32> %t2
387}
388
389define <4 x i8> @test16b(i8 %ele) {
390; CHECK-LABEL: @test16b(
391; CHECK-NEXT:    ret <4 x i8> splat (i8 2)
392;
393  %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
394  %t1 = shl <8 x i8> %t0, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
395  %t2 = shufflevector <8 x i8> %t1, <8 x i8> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
396  ret <4 x i8> %t2
397}
398
399; If composition of two shuffles is identity, shuffles can be removed.
400define <4 x i32> @shuffle_17ident(<4 x i32> %v) {
401; CHECK-LABEL: @shuffle_17ident(
402; CHECK-NEXT:    ret <4 x i32> [[V:%.*]]
403;
404  %shuffle = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
405  %shuffle2 = shufflevector <4 x i32> %shuffle, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 1, i32 2>
406  ret <4 x i32> %shuffle2
407}
408
409; swizzle can be put after operation
410define <4 x i32> @shuffle_17and(<4 x i32> %v1, <4 x i32> %v2) {
411; CHECK-LABEL: @shuffle_17and(
412; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i32> [[V1:%.*]], [[V2:%.*]]
413; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
414; CHECK-NEXT:    ret <4 x i32> [[R]]
415;
416  %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
417  %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
418  %r = and <4 x i32> %t1, %t2
419  ret <4 x i32> %r
420}
421
422declare void @use(<2 x float>)
423
424; One extra use is ok to transform.
425
426define <2 x float> @shuffle_fadd_multiuse(<2 x float> %v1, <2 x float> %v2) {
427; CHECK-LABEL: @shuffle_fadd_multiuse(
428; CHECK-NEXT:    [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
429; CHECK-NEXT:    [[TMP1:%.*]] = fadd <2 x float> [[V1]], [[V2:%.*]]
430; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
431; CHECK-NEXT:    call void @use(<2 x float> [[T1]])
432; CHECK-NEXT:    ret <2 x float> [[R]]
433;
434  %t1 = shufflevector <2 x float> %v1, <2 x float> poison, <2 x i32> <i32 1, i32 0>
435  %t2 = shufflevector <2 x float> %v2, <2 x float> poison, <2 x i32> <i32 1, i32 0>
436  %r = fadd <2 x float> %t1, %t2
437  call void @use(<2 x float> %t1)
438  ret <2 x float> %r
439}
440
441define <2 x float> @shuffle_fdiv_multiuse(<2 x float> %v1, <2 x float> %v2) {
442; CHECK-LABEL: @shuffle_fdiv_multiuse(
443; CHECK-NEXT:    [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
444; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x float> [[V1:%.*]], [[V2]]
445; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
446; CHECK-NEXT:    call void @use(<2 x float> [[T2]])
447; CHECK-NEXT:    ret <2 x float> [[R]]
448;
449  %t1 = shufflevector <2 x float> %v1, <2 x float> poison, <2 x i32> <i32 1, i32 0>
450  %t2 = shufflevector <2 x float> %v2, <2 x float> poison, <2 x i32> <i32 1, i32 0>
451  %r = fdiv <2 x float> %t1, %t2
452  call void @use(<2 x float> %t2)
453  ret <2 x float> %r
454}
455
456; But 2 extra uses would require an extra instruction.
457
458define <2 x float> @shuffle_fsub_multiuse(<2 x float> %v1, <2 x float> %v2) {
459; CHECK-LABEL: @shuffle_fsub_multiuse(
460; CHECK-NEXT:    [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
461; CHECK-NEXT:    [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
462; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> [[T1]], [[T2]]
463; CHECK-NEXT:    call void @use(<2 x float> [[T1]])
464; CHECK-NEXT:    call void @use(<2 x float> [[T2]])
465; CHECK-NEXT:    ret <2 x float> [[R]]
466;
467  %t1 = shufflevector <2 x float> %v1, <2 x float> poison, <2 x i32> <i32 1, i32 0>
468  %t2 = shufflevector <2 x float> %v2, <2 x float> poison, <2 x i32> <i32 1, i32 0>
469  %r = fsub <2 x float> %t1, %t2
470  call void @use(<2 x float> %t1)
471  call void @use(<2 x float> %t2)
472  ret <2 x float> %r
473}
474
475define <4 x i32> @shuffle_17add(<4 x i32> %v1, <4 x i32> %v2) {
476; CHECK-LABEL: @shuffle_17add(
477; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[V1:%.*]], [[V2:%.*]]
478; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
479; CHECK-NEXT:    ret <4 x i32> [[R]]
480;
481  %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
482  %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
483  %r = add <4 x i32> %t1, %t2
484  ret <4 x i32> %r
485}
486
487define <4 x i32> @shuffle_17addnsw(<4 x i32> %v1, <4 x i32> %v2) {
488; CHECK-LABEL: @shuffle_17addnsw(
489; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <4 x i32> [[V1:%.*]], [[V2:%.*]]
490; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
491; CHECK-NEXT:    ret <4 x i32> [[R]]
492;
493  %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
494  %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
495  %r = add nsw <4 x i32> %t1, %t2
496  ret <4 x i32> %r
497}
498
499define <4 x i32> @shuffle_17addnuw(<4 x i32> %v1, <4 x i32> %v2) {
500; CHECK-LABEL: @shuffle_17addnuw(
501; CHECK-NEXT:    [[TMP1:%.*]] = add nuw <4 x i32> [[V1:%.*]], [[V2:%.*]]
502; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
503; CHECK-NEXT:    ret <4 x i32> [[R]]
504;
505  %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
506  %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
507  %r = add nuw <4 x i32> %t1, %t2
508  ret <4 x i32> %r
509}
510
511define <4 x float> @shuffle_17fsub_fast(<4 x float> %v1, <4 x float> %v2) {
512; CHECK-LABEL: @shuffle_17fsub_fast(
513; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <4 x float> [[V1:%.*]], [[V2:%.*]]
514; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
515; CHECK-NEXT:    ret <4 x float> [[R]]
516;
517  %t1 = shufflevector <4 x float> %v1, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
518  %t2 = shufflevector <4 x float> %v2, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
519  %r = fsub fast <4 x float> %t1, %t2
520  ret <4 x float> %r
521}
522
523define <4 x i32> @add_const(<4 x i32> %v) {
524; CHECK-LABEL: @add_const(
525; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[V:%.*]], <i32 44, i32 41, i32 42, i32 43>
526; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
527; CHECK-NEXT:    ret <4 x i32> [[R]]
528;
529  %t1 = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
530  %r = add <4 x i32> %t1, <i32 41, i32 42, i32 43, i32 44>
531  ret <4 x i32> %r
532}
533
534define <4 x i32> @sub_const(<4 x i32> %v) {
535; CHECK-LABEL: @sub_const(
536; CHECK-NEXT:    [[TMP1:%.*]] = sub <4 x i32> <i32 44, i32 43, i32 42, i32 41>, [[V:%.*]]
537; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
538; CHECK-NEXT:    ret <4 x i32> [[R]]
539;
540  %t1 = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
541  %r = sub <4 x i32> <i32 41, i32 42, i32 43, i32 44>, %t1
542  ret <4 x i32> %r
543}
544
545; Math before shuffle requires an extra shuffle.
546
547define <2 x float> @fadd_const_multiuse(<2 x float> %v) {
548; CHECK-LABEL: @fadd_const_multiuse(
549; CHECK-NEXT:    [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
550; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01>
551; CHECK-NEXT:    call void @use(<2 x float> [[T1]])
552; CHECK-NEXT:    ret <2 x float> [[R]]
553;
554  %t1 = shufflevector <2 x float> %v, <2 x float> poison, <2 x i32> <i32 1, i32 0>
555  %r = fadd <2 x float> %t1, <float 41.0, float 42.0>
556  call void @use(<2 x float> %t1)
557  ret <2 x float> %r
558}
559
560; Math before splat allows replacing constant elements with undef lanes.
561
562define <4 x i32> @mul_const_splat(<4 x i32> %v) {
563; CHECK-LABEL: @mul_const_splat(
564; CHECK-NEXT:    [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], <i32 poison, i32 42, i32 poison, i32 poison>
565; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
566; CHECK-NEXT:    ret <4 x i32> [[R]]
567;
568  %t1 = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
569  %r = mul <4 x i32> <i32 42, i32 42, i32 42, i32 42>, %t1
570  ret <4 x i32> %r
571}
572
573; Take 2 elements of a vector and shift each of those by a different amount
574
575define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) {
576; CHECK-LABEL: @lshr_const_half_splat(
577; CHECK-NEXT:    [[TMP1:%.*]] = lshr <4 x i32> <i32 poison, i32 8, i32 9, i32 poison>, [[V:%.*]]
578; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
579; CHECK-NEXT:    ret <4 x i32> [[R]]
580;
581  %t1 = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
582  %r = lshr <4 x i32> <i32 8, i32 8, i32 9, i32 9>, %t1
583  ret <4 x i32> %r
584}
585
586; We can't change this because there's no pre-shuffle version of the fmul constant.
587
588define <2 x float> @fmul_const_invalid_constant(<2 x float> %v) {
589; CHECK-LABEL: @fmul_const_invalid_constant(
590; CHECK-NEXT:    [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
591; CHECK-NEXT:    [[R:%.*]] = fmul <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01>
592; CHECK-NEXT:    ret <2 x float> [[R]]
593;
594  %t1 = shufflevector <2 x float> %v, <2 x float> poison, <2 x i32> <i32 0, i32 0>
595  %r = fmul <2 x float> %t1, <float 41.0, float 42.0>
596  ret <2 x float> %r
597}
598
599; Reduce the width of the binop by moving it ahead of a shuffle.
600
601define <4 x i8> @widening_shuffle_add_1(<2 x i8> %x) {
602; CHECK-LABEL: @widening_shuffle_add_1(
603; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 42, i8 43>
604; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
605; CHECK-NEXT:    ret <4 x i8> [[R]]
606;
607  %widex = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
608  %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
609  ret <4 x i8> %r
610}
611
612; Reduce the width of the binop by moving it ahead of a shuffle.
613
614define <4 x i8> @widening_shuffle_add_2(<2 x i8> %x) {
615; CHECK-LABEL: @widening_shuffle_add_2(
616; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 43, i8 42>
617; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> <i32 1, i32 0, i32 poison, i32 poison>
618; CHECK-NEXT:    ret <4 x i8> [[R]]
619;
620  %widex = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
621  %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
622  ret <4 x i8> %r
623}
624
625; Negative test - widening shuffles have the same mask/constant constraint as non-size-changing shuffles.
626
627define <4 x i8> @widening_shuffle_add_invalid_constant(<2 x i8> %x) {
628; CHECK-LABEL: @widening_shuffle_add_invalid_constant(
629; CHECK-NEXT:    [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> poison, <4 x i32> <i32 1, i32 1, i32 poison, i32 poison>
630; CHECK-NEXT:    [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45>
631; CHECK-NEXT:    ret <4 x i8> [[R]]
632;
633  %widex = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 1, i32 undef, i32 undef>
634  %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
635  ret <4 x i8> %r
636}
637
638; Negative test - widening shuffles have an additional constraint: they must not extend with anything but undefs.
639
640define <4 x i8> @widening_shuffle_add_invalid_mask(<2 x i8> %x) {
641; CHECK-LABEL: @widening_shuffle_add_invalid_mask(
642; CHECK-NEXT:    [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 0>
643; CHECK-NEXT:    [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45>
644; CHECK-NEXT:    ret <4 x i8> [[R]]
645;
646  %widex = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 0>
647  %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45>
648  ret <4 x i8> %r
649}
650
651; A binop that produces undef in the high lanes can be moved before the shuffle.
652; This is ok because 'shl C, undef --> undef'.
653
654define <4 x i16> @widening_shuffle_shl_constant_op0(<2 x i16> %v) {
655; CHECK-LABEL: @widening_shuffle_shl_constant_op0(
656; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i16> <i16 42, i16 -42>, [[V:%.*]]
657; CHECK-NEXT:    [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
658; CHECK-NEXT:    ret <4 x i16> [[BO]]
659;
660  %shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
661  %bo = shl <4 x i16> <i16 42, i16 -42, i16 -1, i16 -1>, %shuf
662  ret <4 x i16> %bo
663}
664
665; A binop that produces undef in the high lanes can be moved before the shuffle.
666; This is ok because 'shl undef, 0 --> undef'.
667
668define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
669; CHECK-LABEL: @widening_shuffle_shl_constant_op1(
670; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
671; CHECK-NEXT:    [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
672; CHECK-NEXT:    ret <4 x i16> [[BO]]
673;
674  %shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
675  %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 0, i16 0>
676  ret <4 x i16> %bo
677}
678
679; This is valid for poison, but would not be valid for undef.
680
681define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
682; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
683; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
684; CHECK-NEXT:    [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
685; CHECK-NEXT:    ret <4 x i16> [[BO]]
686;
687  %shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
688  %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 1, i16 2>
689  ret <4 x i16> %bo
690}
691
692define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
693; CHECK-LABEL: @widening_shuffle_or(
694; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
695; CHECK-NEXT:    [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
696; CHECK-NEXT:    ret <4 x i16> [[BO]]
697;
698  %shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
699  %bo = or <4 x i16> %shuf, <i16 42, i16 -42, i16 -1, i16 -1>
700  ret <4 x i16> %bo
701}
702
703define <4 x i32> @shuffle_17add2(<4 x i32> %v) {
704; CHECK-LABEL: @shuffle_17add2(
705; CHECK-NEXT:    [[TMP1:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 1)
706; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
707;
708  %t1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
709  %t2 = add <4 x i32> %t1, %t1
710  %r = shufflevector <4 x i32> %t2, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
711  ret <4 x i32> %r
712}
713
714define <4 x i32> @shuffle_17mulsplat(<4 x i32> %v) {
715; CHECK-LABEL: @shuffle_17mulsplat(
716; CHECK-NEXT:    [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], [[V]]
717; CHECK-NEXT:    [[M1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
718; CHECK-NEXT:    ret <4 x i32> [[M1]]
719;
720  %s1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer
721  %m1 = mul <4 x i32> %s1, %s1
722  %s2 = shufflevector <4 x i32> %m1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
723  ret <4 x i32> %s2
724}
725
726; Do not reorder shuffle and binop if LHS of shuffles are of different size
727define <2 x i32> @pr19717(<4 x i32> %in0, <2 x i32> %in1) {
728; CHECK-LABEL: @pr19717(
729; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[IN0:%.*]], <4 x i32> poison, <2 x i32> zeroinitializer
730; CHECK-NEXT:    [[SHUFFLE4:%.*]] = shufflevector <2 x i32> [[IN1:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer
731; CHECK-NEXT:    [[MUL:%.*]] = mul <2 x i32> [[SHUFFLE]], [[SHUFFLE4]]
732; CHECK-NEXT:    ret <2 x i32> [[MUL]]
733;
734  %shuffle = shufflevector <4 x i32> %in0, <4 x i32> %in0, <2 x i32> zeroinitializer
735  %shuffle4 = shufflevector <2 x i32> %in1, <2 x i32> %in1, <2 x i32> zeroinitializer
736  %mul = mul <2 x i32> %shuffle, %shuffle4
737  ret <2 x i32> %mul
738}
739
740define <4 x i16> @pr19717a(<8 x i16> %in0, <8 x i16> %in1) {
741; CHECK-LABEL: @pr19717a(
742; CHECK-NEXT:    [[TMP1:%.*]] = mul <8 x i16> [[IN0:%.*]], [[IN1:%.*]]
743; CHECK-NEXT:    [[MUL:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
744; CHECK-NEXT:    ret <4 x i16> [[MUL]]
745;
746  %shuffle = shufflevector <8 x i16> %in0, <8 x i16> %in0, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
747  %shuffle1 = shufflevector <8 x i16> %in1, <8 x i16> %in1, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
748  %mul = mul <4 x i16> %shuffle, %shuffle1
749  ret <4 x i16> %mul
750}
751
752define <8 x i8> @pr19730(<16 x i8> %in0) {
753; CHECK-LABEL: @pr19730(
754; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <16 x i8> [[IN0:%.*]], <16 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
755; CHECK-NEXT:    [[SHUFFLE1:%.*]] = shufflevector <8 x i8> [[SHUFFLE]], <8 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
756; CHECK-NEXT:    ret <8 x i8> [[SHUFFLE1]]
757;
758  %shuffle = shufflevector <16 x i8> %in0, <16 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
759  %shuffle1 = shufflevector <8 x i8> %shuffle, <8 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
760  ret <8 x i8> %shuffle1
761}
762
763define i32 @pr19737(<4 x i32> %in0) {
764; CHECK-LABEL: @pr19737(
765; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <4 x i32> [[IN0:%.*]], i64 0
766; CHECK-NEXT:    ret i32 [[TMP1]]
767;
768  %shuffle.i = shufflevector <4 x i32> zeroinitializer, <4 x i32> %in0, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
769  %neg.i = xor <4 x i32> %shuffle.i, <i32 -1, i32 -1, i32 -1, i32 -1>
770  %and.i = and <4 x i32> %in0, %neg.i
771  %rv = extractelement <4 x i32> %and.i, i32 0
772  ret i32 %rv
773}
774
775; In PR20059 ( http://llvm.org/pr20059 ), shufflevector operations are reordered/removed
776; for an srem operation. This is not a valid optimization because it may cause a trap
777; on div-by-zero.
778
779define <4 x i32> @pr20059(<4 x i32> %p1, <4 x i32> %p2) {
780; CHECK-LABEL: @pr20059(
781; CHECK-NEXT:    [[SPLAT1:%.*]] = shufflevector <4 x i32> [[P1:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer
782; CHECK-NEXT:    [[SPLAT2:%.*]] = shufflevector <4 x i32> [[P2:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer
783; CHECK-NEXT:    [[RETVAL:%.*]] = srem <4 x i32> [[SPLAT1]], [[SPLAT2]]
784; CHECK-NEXT:    ret <4 x i32> [[RETVAL]]
785;
786  %splat1 = shufflevector <4 x i32> %p1, <4 x i32> poison, <4 x i32> zeroinitializer
787  %splat2 = shufflevector <4 x i32> %p2, <4 x i32> poison, <4 x i32> zeroinitializer
788  %retval = srem <4 x i32> %splat1, %splat2
789  ret <4 x i32> %retval
790}
791
792define <4 x i32> @pr20114(<4 x i32> %__mask) {
793; CHECK-LABEL: @pr20114(
794; CHECK-NEXT:    [[MASK01_I:%.*]] = shufflevector <4 x i32> [[__MASK:%.*]], <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 1, i32 1>
795; CHECK-NEXT:    [[MASKED_NEW_I_I_I:%.*]] = and <4 x i32> [[MASK01_I]], bitcast (<2 x i64> <i64 ptrtoint (ptr @pr20114 to i64), i64 ptrtoint (ptr @pr20114 to i64)> to <4 x i32>)
796; CHECK-NEXT:    ret <4 x i32> [[MASKED_NEW_I_I_I]]
797;
798  %mask01.i = shufflevector <4 x i32> %__mask, <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 1, i32 1>
799  %masked_new.i.i.i = and <4 x i32> bitcast (<2 x i64> <i64 ptrtoint (ptr @pr20114 to i64), i64 ptrtoint (ptr @pr20114 to i64)> to <4 x i32>), %mask01.i
800  ret <4 x i32> %masked_new.i.i.i
801}
802
803define <2 x ptr> @pr23113(<4 x ptr> %A) {
804; CHECK-LABEL: @pr23113(
805; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x ptr> [[A:%.*]], <4 x ptr> poison, <2 x i32> <i32 0, i32 1>
806; CHECK-NEXT:    ret <2 x ptr> [[TMP1]]
807;
808  %1 = shufflevector <4 x ptr> %A, <4 x ptr> poison, <2 x i32> <i32 0, i32 1>
809  ret <2 x ptr> %1
810}
811
812; Unused lanes in the new binop should not kill the entire op (although it may simplify anyway as shown here).
813
814define <2 x i32> @PR37648(<2 x i32> %x) {
815; CHECK-LABEL: @PR37648(
816; CHECK-NEXT:    ret <2 x i32> zeroinitializer
817;
818  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
819  %r = urem <2 x i32> %splat, <i32 1, i32 1>
820  ret <2 x i32> %r
821}
822
823; Test shuffle followed by binop with splat constant for all 18 binop opcodes.
824; Test with constant as operand 0 and operand 1 for non-commutative opcodes.
825
826define <2 x i32> @add_splat_constant(<2 x i32> %x) {
827; CHECK-LABEL: @add_splat_constant(
828; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 42, i32 poison>
829; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
830; CHECK-NEXT:    ret <2 x i32> [[R]]
831;
832  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
833  %r = add <2 x i32> %splat, <i32 42, i32 42>
834  ret <2 x i32> %r
835}
836
837define <2 x i32> @sub_splat_constant0(<2 x i32> %x) {
838; CHECK-LABEL: @sub_splat_constant0(
839; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> <i32 42, i32 poison>, [[X:%.*]]
840; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
841; CHECK-NEXT:    ret <2 x i32> [[R]]
842;
843  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
844  %r = sub <2 x i32> <i32 42, i32 42>, %splat
845  ret <2 x i32> %r
846}
847
848define <2 x i32> @sub_splat_constant1(<2 x i32> %x) {
849; CHECK-LABEL: @sub_splat_constant1(
850; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 -42, i32 poison>
851; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
852; CHECK-NEXT:    ret <2 x i32> [[R]]
853;
854  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
855  %r = sub <2 x i32> %splat, <i32 42, i32 42>
856  ret <2 x i32> %r
857}
858
859define <2 x i32> @mul_splat_constant(<2 x i32> %x) {
860; CHECK-LABEL: @mul_splat_constant(
861; CHECK-NEXT:    [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], <i32 42, i32 poison>
862; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
863; CHECK-NEXT:    ret <2 x i32> [[R]]
864;
865  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
866  %r = mul <2 x i32> %splat, <i32 42, i32 42>
867  ret <2 x i32> %r
868}
869
870define <2 x i32> @shl_splat_constant0(<2 x i32> %x) {
871; CHECK-LABEL: @shl_splat_constant0(
872; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
873; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
874; CHECK-NEXT:    ret <2 x i32> [[R]]
875;
876  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
877  %r = shl <2 x i32> <i32 5, i32 5>, %splat
878  ret <2 x i32> %r
879}
880
881define <2 x i32> @shl_splat_constant1(<2 x i32> %x) {
882; CHECK-LABEL: @shl_splat_constant1(
883; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 0>
884; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
885; CHECK-NEXT:    ret <2 x i32> [[R]]
886;
887  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
888  %r = shl <2 x i32> %splat, <i32 5, i32 5>
889  ret <2 x i32> %r
890}
891
892define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) {
893; CHECK-LABEL: @ashr_splat_constant0(
894; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
895; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
896; CHECK-NEXT:    ret <2 x i32> [[R]]
897;
898  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
899  %r = ashr <2 x i32> <i32 5, i32 5>, %splat
900  ret <2 x i32> %r
901}
902
903define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) {
904; CHECK-LABEL: @ashr_splat_constant1(
905; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 0>
906; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
907; CHECK-NEXT:    ret <2 x i32> [[R]]
908;
909  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
910  %r = ashr <2 x i32> %splat, <i32 5, i32 5>
911  ret <2 x i32> %r
912}
913
914define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) {
915; CHECK-LABEL: @lshr_splat_constant0(
916; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
917; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
918; CHECK-NEXT:    ret <2 x i32> [[R]]
919;
920  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
921  %r = lshr <2 x i32> <i32 5, i32 5>, %splat
922  ret <2 x i32> %r
923}
924
925define <2 x i32> @lshr_splat_constant1(<2 x i32> %x) {
926; CHECK-LABEL: @lshr_splat_constant1(
927; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 0>
928; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
929; CHECK-NEXT:    ret <2 x i32> [[R]]
930;
931  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
932  %r = lshr <2 x i32> %splat, <i32 5, i32 5>
933  ret <2 x i32> %r
934}
935
936define <2 x i32> @urem_splat_constant0(<2 x i32> %x) {
937; CHECK-LABEL: @urem_splat_constant0(
938; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer
939; CHECK-NEXT:    [[R:%.*]] = urem <2 x i32> splat (i32 42), [[SPLAT]]
940; CHECK-NEXT:    ret <2 x i32> [[R]]
941;
942  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
943  %r = urem <2 x i32> <i32 42, i32 42>, %splat
944  ret <2 x i32> %r
945}
946
947define <2 x i32> @urem_splat_constant1(<2 x i32> %x) {
948; CHECK-LABEL: @urem_splat_constant1(
949; CHECK-NEXT:    [[TMP1:%.*]] = urem <2 x i32> [[X:%.*]], <i32 42, i32 1>
950; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
951; CHECK-NEXT:    ret <2 x i32> [[R]]
952;
953  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
954  %r = urem <2 x i32> %splat, <i32 42, i32 42>
955  ret <2 x i32> %r
956}
957
958define <2 x i32> @srem_splat_constant0(<2 x i32> %x) {
959; CHECK-LABEL: @srem_splat_constant0(
960; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer
961; CHECK-NEXT:    [[R:%.*]] = srem <2 x i32> splat (i32 42), [[SPLAT]]
962; CHECK-NEXT:    ret <2 x i32> [[R]]
963;
964  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
965  %r = srem <2 x i32> <i32 42, i32 42>, %splat
966  ret <2 x i32> %r
967}
968
969define <2 x i32> @srem_splat_constant1(<2 x i32> %x) {
970; CHECK-LABEL: @srem_splat_constant1(
971; CHECK-NEXT:    [[TMP1:%.*]] = srem <2 x i32> [[X:%.*]], <i32 42, i32 1>
972; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
973; CHECK-NEXT:    ret <2 x i32> [[R]]
974;
975  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
976  %r = srem <2 x i32> %splat, <i32 42, i32 42>
977  ret <2 x i32> %r
978}
979
980define <2 x i32> @udiv_splat_constant0(<2 x i32> %x) {
981; CHECK-LABEL: @udiv_splat_constant0(
982; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer
983; CHECK-NEXT:    [[R:%.*]] = udiv <2 x i32> splat (i32 42), [[SPLAT]]
984; CHECK-NEXT:    ret <2 x i32> [[R]]
985;
986  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
987  %r = udiv <2 x i32> <i32 42, i32 42>, %splat
988  ret <2 x i32> %r
989}
990
991define <2 x i32> @udiv_splat_constant1(<2 x i32> %x) {
992; CHECK-LABEL: @udiv_splat_constant1(
993; CHECK-NEXT:    [[TMP1:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 42, i32 1>
994; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
995; CHECK-NEXT:    ret <2 x i32> [[R]]
996;
997  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
998  %r = udiv <2 x i32> %splat, <i32 42, i32 42>
999  ret <2 x i32> %r
1000}
1001
1002define <2 x i32> @sdiv_splat_constant0(<2 x i32> %x) {
1003; CHECK-LABEL: @sdiv_splat_constant0(
1004; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer
1005; CHECK-NEXT:    [[R:%.*]] = sdiv <2 x i32> splat (i32 42), [[SPLAT]]
1006; CHECK-NEXT:    ret <2 x i32> [[R]]
1007;
1008  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
1009  %r = sdiv <2 x i32> <i32 42, i32 42>, %splat
1010  ret <2 x i32> %r
1011}
1012
1013define <2 x i32> @sdiv_splat_constant1(<2 x i32> %x) {
1014; CHECK-LABEL: @sdiv_splat_constant1(
1015; CHECK-NEXT:    [[TMP1:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 42, i32 1>
1016; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
1017; CHECK-NEXT:    ret <2 x i32> [[R]]
1018;
1019  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
1020  %r = sdiv <2 x i32> %splat, <i32 42, i32 42>
1021  ret <2 x i32> %r
1022}
1023
1024define <2 x i32> @and_splat_constant(<2 x i32> %x) {
1025; CHECK-LABEL: @and_splat_constant(
1026; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1027; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
1028; CHECK-NEXT:    ret <2 x i32> [[R]]
1029;
1030  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
1031  %r = and <2 x i32> %splat, <i32 42, i32 42>
1032  ret <2 x i32> %r
1033}
1034
1035define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
1036; CHECK-LABEL: @and_constant_mask_poison(
1037; CHECK-NEXT:  entry:
1038; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1039; CHECK-NEXT:    ret <4 x i16> [[AND]]
1040;
1041entry:
1042  %shuffle = shufflevector <4 x i16> %add, <4 x i16> poison, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1043  %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1044  ret <4 x i16> %and
1045}
1046
1047define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
1048; CHECK-LABEL: @and_constant_mask_poison_2(
1049; CHECK-NEXT:  entry:
1050; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1051; CHECK-NEXT:    ret <4 x i16> [[AND]]
1052;
1053entry:
1054  %shuffle = shufflevector <4 x i16> %add, <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 undef>
1055  %and = and <4 x i16> %shuffle, <i16 -1, i16 -1, i16 -1, i16 -0>
1056  ret <4 x i16> %and
1057}
1058
1059; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1060define <4 x i16> @and_constant_mask_poison_3(<4 x i16> %add) {
1061; CHECK-LABEL: @and_constant_mask_poison_3(
1062; CHECK-NEXT:  entry:
1063; CHECK-NEXT:    ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
1064;
1065entry:
1066  %shuffle = shufflevector <4 x i16> %add, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
1067  %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 0, i16 -1>
1068  ret <4 x i16> %and
1069}
1070
1071; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1072define <4 x i16> @and_constant_mask_poison_4(<4 x i16> %add) {
1073; CHECK-LABEL: @and_constant_mask_poison_4(
1074; CHECK-NEXT:  entry:
1075; CHECK-NEXT:    [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison>
1076; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 poison>
1077; CHECK-NEXT:    ret <4 x i16> [[AND]]
1078;
1079entry:
1080  %shuffle = shufflevector <4 x i16> %add, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
1081  %and = and <4 x i16> %shuffle, <i16 9, i16 20, i16 20, i16 -1>
1082  ret <4 x i16> %and
1083}
1084
1085define <4 x i16> @and_constant_mask_not_undef(<4 x i16> %add) {
1086; CHECK-LABEL: @and_constant_mask_not_undef(
1087; CHECK-NEXT:  entry:
1088; CHECK-NEXT:    [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 poison, i16 -1, i16 0, i16 0>
1089; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1090; CHECK-NEXT:    ret <4 x i16> [[AND]]
1091;
1092entry:
1093  %shuffle = shufflevector <4 x i16> %add, <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1094  %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1095  ret <4 x i16> %and
1096}
1097
1098define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
1099; CHECK-LABEL: @or_constant_mask_poison(
1100; CHECK-NEXT:  entry:
1101; CHECK-NEXT:    [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1102; CHECK-NEXT:    ret <4 x i16> [[OR]]
1103;
1104entry:
1105  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1106  %or = or <4 x i16> %shuffle, <i16 -1, i16 -1, i16 0, i16 0>
1107  ret <4 x i16> %or
1108}
1109
1110define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
1111; CHECK-LABEL: @or_constant_mask_poison_2(
1112; CHECK-NEXT:  entry:
1113; CHECK-NEXT:    [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1114; CHECK-NEXT:    ret <4 x i16> [[OR]]
1115;
1116entry:
1117  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1118  %or = or <4 x i16> %shuffle, <i16 -1, i16 0, i16 0, i16 -1>
1119  ret <4 x i16> %or
1120}
1121
1122; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1123define <4 x i16> @or_constant_mask_poison_3(<4 x i16> %in) {
1124; CHECK-LABEL: @or_constant_mask_poison_3(
1125; CHECK-NEXT:  entry:
1126; CHECK-NEXT:    ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
1127;
1128entry:
1129  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1130  %or = or <4 x i16> %shuffle, <i16 0, i16 -1, i16 -1, i16 0>
1131  ret <4 x i16> %or
1132}
1133
1134; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1135define <4 x i16> @or_constant_mask_poison_4(<4 x i16> %in) {
1136; CHECK-LABEL: @or_constant_mask_poison_4(
1137; CHECK-NEXT:  entry:
1138; CHECK-NEXT:    [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison>
1139; CHECK-NEXT:    [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1140; CHECK-NEXT:    ret <4 x i16> [[OR]]
1141;
1142entry:
1143  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
1144  %or = or <4 x i16> %shuffle, <i16 0, i16 99, i16 99, i16 0>
1145  ret <4 x i16> %or
1146}
1147
1148define <4 x i16> @or_constant_mask_not_undef(<4 x i16> %in) {
1149; CHECK-LABEL: @or_constant_mask_not_undef(
1150; CHECK-NEXT:  entry:
1151; CHECK-NEXT:    [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 -1, i16 0, i16 0>
1152; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1153; CHECK-NEXT:    ret <4 x i16> [[AND]]
1154;
1155entry:
1156  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1>
1157  %and = or <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1>
1158  ret <4 x i16> %and
1159}
1160
1161define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) {
1162; CHECK-LABEL: @shl_constant_mask_undef(
1163; CHECK-NEXT:  entry:
1164; CHECK-NEXT:    [[TMP0:%.*]] = shl <4 x i16> [[IN:%.*]], <i16 10, i16 0, i16 0, i16 0>
1165; CHECK-NEXT:    [[SHL:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
1166; CHECK-NEXT:    ret <4 x i16> [[SHL]]
1167;
1168entry:
1169  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 0, i32 undef, i32 1, i32 1>
1170  %shl = shl <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1171  ret <4 x i16> %shl
1172}
1173
1174define <4 x i16> @add_constant_mask_undef(<4 x i16> %in) {
1175; CHECK-LABEL: @add_constant_mask_undef(
1176; CHECK-NEXT:  entry:
1177; CHECK-NEXT:    [[ADD:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1178; CHECK-NEXT:    ret <4 x i16> [[ADD]]
1179;
1180entry:
1181  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1182  %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1183  ret <4 x i16> %add
1184}
1185
1186define <4 x i16> @add_constant_mask_undef_2(<4 x i16> %in) {
1187; CHECK-LABEL: @add_constant_mask_undef_2(
1188; CHECK-NEXT:  entry:
1189; CHECK-NEXT:    [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 3, i16 poison>
1190; CHECK-NEXT:    [[ADD:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 2, i32 1, i32 1>
1191; CHECK-NEXT:    ret <4 x i16> [[ADD]]
1192;
1193entry:
1194  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 2, i32 1, i32 1>
1195  %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1196  ret <4 x i16> %add
1197}
1198
1199define <4 x i16> @sub_constant_mask_undef(<4 x i16> %in) {
1200; CHECK-LABEL: @sub_constant_mask_undef(
1201; CHECK-NEXT:  entry:
1202; CHECK-NEXT:    [[SUB:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1203; CHECK-NEXT:    ret <4 x i16> [[SUB]]
1204;
1205entry:
1206  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1>
1207  %sub = sub <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0>
1208  ret <4 x i16> %sub
1209}
1210
1211define <4 x i16> @sub_constant_mask_undef_2(<4 x i16> %in) {
1212; CHECK-LABEL: @sub_constant_mask_undef_2(
1213; CHECK-NEXT:  entry:
1214; CHECK-NEXT:    [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 -10, i16 poison>
1215; CHECK-NEXT:    [[SUB:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 poison>
1216; CHECK-NEXT:    ret <4 x i16> [[SUB]]
1217;
1218entry:
1219  %shuffle = shufflevector <4 x i16> %in, <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 undef>
1220  %sub = sub <4 x i16> %shuffle, <i16 0, i16 0, i16 10, i16 99>
1221  ret <4 x i16> %sub
1222}
1223
1224define <2 x i32> @or_splat_constant(<2 x i32> %x) {
1225; CHECK-LABEL: @or_splat_constant(
1226; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1227; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
1228; CHECK-NEXT:    ret <2 x i32> [[R]]
1229;
1230  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
1231  %r = or <2 x i32> %splat, <i32 42, i32 42>
1232  ret <2 x i32> %r
1233}
1234
1235define <2 x i32> @xor_splat_constant(<2 x i32> %x) {
1236; CHECK-LABEL: @xor_splat_constant(
1237; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], <i32 42, i32 poison>
1238; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
1239; CHECK-NEXT:    ret <2 x i32> [[R]]
1240;
1241  %splat = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> zeroinitializer
1242  %r = xor <2 x i32> %splat, <i32 42, i32 42>
1243  ret <2 x i32> %r
1244}
1245
1246define <2 x float> @fadd_splat_constant(<2 x float> %x) {
1247; CHECK-LABEL: @fadd_splat_constant(
1248; CHECK-NEXT:    [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1249; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1250; CHECK-NEXT:    ret <2 x float> [[R]]
1251;
1252  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1253  %r = fadd <2 x float> %splat, <float 42.0, float 42.0>
1254  ret <2 x float> %r
1255}
1256
1257define <2 x float> @fsub_splat_constant0(<2 x float> %x) {
1258; CHECK-LABEL: @fsub_splat_constant0(
1259; CHECK-NEXT:    [[TMP1:%.*]] = fsub <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1260; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1261; CHECK-NEXT:    ret <2 x float> [[R]]
1262;
1263  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1264  %r = fsub <2 x float> <float 42.0, float 42.0>, %splat
1265  ret <2 x float> %r
1266}
1267
1268define <2 x float> @fsub_splat_constant1(<2 x float> %x) {
1269; CHECK-LABEL: @fsub_splat_constant1(
1270; CHECK-NEXT:    [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float poison>
1271; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1272; CHECK-NEXT:    ret <2 x float> [[R]]
1273;
1274  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1275  %r = fsub <2 x float> %splat, <float 42.0, float 42.0>
1276  ret <2 x float> %r
1277}
1278
1279define <2 x float> @fneg(<2 x float> %x) {
1280; CHECK-LABEL: @fneg(
1281; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
1282; CHECK-NEXT:    [[R:%.*]] = fneg <2 x float> [[TMP1]]
1283; CHECK-NEXT:    ret <2 x float> [[R]]
1284;
1285  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1286  %r = fsub <2 x float> <float -0.0, float -0.0>, %splat
1287  ret <2 x float> %r
1288}
1289
1290define <2 x float> @fmul_splat_constant(<2 x float> %x) {
1291; CHECK-LABEL: @fmul_splat_constant(
1292; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1293; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1294; CHECK-NEXT:    ret <2 x float> [[R]]
1295;
1296  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1297  %r = fmul <2 x float> %splat, <float 42.0, float 42.0>
1298  ret <2 x float> %r
1299}
1300
1301define <2 x float> @fdiv_splat_constant0(<2 x float> %x) {
1302; CHECK-LABEL: @fdiv_splat_constant0(
1303; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1304; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1305; CHECK-NEXT:    ret <2 x float> [[R]]
1306;
1307  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1308  %r = fdiv <2 x float> <float 42.0, float 42.0>, %splat
1309  ret <2 x float> %r
1310}
1311
1312define <2 x float> @fdiv_splat_constant1(<2 x float> %x) {
1313; CHECK-LABEL: @fdiv_splat_constant1(
1314; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1315; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1316; CHECK-NEXT:    ret <2 x float> [[R]]
1317;
1318  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1319  %r = fdiv <2 x float> %splat, <float 42.0, float 42.0>
1320  ret <2 x float> %r
1321}
1322
1323define <2 x float> @frem_splat_constant0(<2 x float> %x) {
1324; CHECK-LABEL: @frem_splat_constant0(
1325; CHECK-NEXT:    [[TMP1:%.*]] = frem <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]]
1326; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1327; CHECK-NEXT:    ret <2 x float> [[R]]
1328;
1329  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1330  %r = frem <2 x float> <float 42.0, float 42.0>, %splat
1331  ret <2 x float> %r
1332}
1333
1334define <2 x float> @frem_splat_constant1(<2 x float> %x) {
1335; CHECK-LABEL: @frem_splat_constant1(
1336; CHECK-NEXT:    [[TMP1:%.*]] = frem <2 x float> [[X:%.*]], <float 4.200000e+01, float poison>
1337; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1338; CHECK-NEXT:    ret <2 x float> [[R]]
1339;
1340  %splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1341  %r = frem <2 x float> %splat, <float 42.0, float 42.0>
1342  ret <2 x float> %r
1343}
1344
1345; Equivalent shuffle masks, but only one is a narrowing op.
1346
1347define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) {
1348; CHECK-LABEL: @PR40734(
1349; CHECK-NEXT:    [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> <i32 0, i32 1>
1350; CHECK-NEXT:    [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> poison, <2 x i32> <i32 0, i32 1>
1351; CHECK-NEXT:    [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]]
1352; CHECK-NEXT:    ret <2 x i1> [[R]]
1353;
1354  %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> <i32 0, i32 1>
1355  %narrow = shufflevector <4 x i1> %y, <4 x i1> poison, <2 x i32> <i32 0, i32 1>
1356  %r = and <2 x i1> %widen, %narrow
1357  ret <2 x i1> %r
1358}
1359
1360; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically.
1361
1362define <7 x i8> @insert_subvector_shuffles(<3 x i8> %x, <3 x i8> %y) {
1363; CHECK-LABEL: @insert_subvector_shuffles(
1364; CHECK-NEXT:    [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <7 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
1365; CHECK-NEXT:    [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <7 x i32> <i32 poison, i32 1, i32 2, i32 poison, i32 poison, i32 poison, i32 poison>
1366; CHECK-NEXT:    [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <7 x i32> <i32 0, i32 8, i32 1, i32 poison, i32 8, i32 1, i32 9>
1367; CHECK-NEXT:    ret <7 x i8> [[S3]]
1368;
1369  %s1 = shufflevector <3 x i8> %x, <3 x i8> poison, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1370  %s2 = shufflevector <3 x i8> %y, <3 x i8> poison, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef>
1371  %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>
1372  ret <7 x i8> %s3
1373}
1374
1375define <8 x i8> @insert_subvector_shuffles_pow2elts(<2 x i8> %x, <2 x i8> %y) {
1376; CHECK-LABEL: @insert_subvector_shuffles_pow2elts(
1377; CHECK-NEXT:    [[S3:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <8 x i32> <i32 0, i32 2, i32 1, i32 poison, i32 2, i32 1, i32 3, i32 0>
1378; CHECK-NEXT:    ret <8 x i8> [[S3]]
1379;
1380  %s1 = shufflevector <2 x i8> %x, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1381  %s2 = shufflevector <2 x i8> %y, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1382  %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>
1383  ret <8 x i8> %s3
1384}
1385
1386; The last shuffle may change the vector type.
1387; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically.
1388
1389define <2 x i8> @insert_subvector_shuffles_narrowing(<3 x i8> %x, <3 x i8> %y) {
1390; CHECK-LABEL: @insert_subvector_shuffles_narrowing(
1391; CHECK-NEXT:    [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <7 x i32> <i32 0, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
1392; CHECK-NEXT:    [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <7 x i32> <i32 poison, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
1393; CHECK-NEXT:    [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <2 x i32> <i32 0, i32 8>
1394; CHECK-NEXT:    ret <2 x i8> [[S3]]
1395;
1396  %s1 = shufflevector <3 x i8> %x, <3 x i8> poison, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1397  %s2 = shufflevector <3 x i8> %y, <3 x i8> poison, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef>
1398  %s3 = shufflevector <7 x i8> %s1, <7 x i8> %s2, <2 x i32> <i32 0, i32 8>
1399  ret <2 x i8> %s3
1400}
1401
1402define <2 x i8> @insert_subvector_shuffles_narrowing_pow2elts(<4 x i8> %x, <4 x i8> %y) {
1403; CHECK-LABEL: @insert_subvector_shuffles_narrowing_pow2elts(
1404; CHECK-NEXT:    [[S3:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 4>
1405; CHECK-NEXT:    ret <2 x i8> [[S3]]
1406;
1407  %s1 = shufflevector <4 x i8> %x, <4 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
1408  %s2 = shufflevector <4 x i8> %y, <4 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
1409  %s3 = shufflevector <8 x i8> %s1, <8 x i8> %s2, <2 x i32> <i32 0, i32 8>
1410  ret <2 x i8> %s3
1411}
1412
1413; Similar to above, but this reduces to a widen with undefs of 'x'.
1414
1415define <4 x double> @insert_subvector_shuffles_identity(<2 x double> %x) {
1416; CHECK-LABEL: @insert_subvector_shuffles_identity(
1417; CHECK-NEXT:    [[S3:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
1418; CHECK-NEXT:    ret <4 x double> [[S3]]
1419;
1420  %s1 = shufflevector <2 x double> %x, <2 x double> poison, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef>
1421  %s2 = shufflevector <2 x double> %x, <2 x double> poison, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1422  %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>
1423  ret <4 x double> %s3
1424}
1425
1426; Negative test - not identity with padding (although this could be folded with better analysis).
1427
1428define <4 x double> @not_insert_subvector_shuffle(<2 x double> %x) {
1429; CHECK-LABEL: @not_insert_subvector_shuffle(
1430; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 1>
1431; CHECK-NEXT:    [[S2:%.*]] = shufflevector <2 x double> [[X]], <2 x double> poison, <4 x i32> <i32 0, i32 poison, i32 poison, i32 poison>
1432; CHECK-NEXT:    [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 7, i32 poison>
1433; CHECK-NEXT:    ret <4 x double> [[S3]]
1434;
1435  %s1 = shufflevector <2 x double> %x, <2 x double> poison, <4 x i32> <i32 undef, i32 1, i32 undef, i32 1>
1436  %s2 = shufflevector <2 x double> %x, <2 x double> poison, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1437  %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 7, i32 undef>
1438  ret <4 x double> %s3
1439}
1440
1441; Negative test - operands are not the same size (although this could be partly folded with better analysis).
1442
1443define <4 x double> @not_insert_subvector_shuffles_with_same_size(<2 x double> %x, <3 x double> %y) {
1444; CHECK-LABEL: @not_insert_subvector_shuffles_with_same_size(
1445; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 poison>
1446; CHECK-NEXT:    [[S2:%.*]] = shufflevector <3 x double> [[Y:%.*]], <3 x double> poison, <4 x i32> <i32 0, i32 poison, i32 poison, i32 poison>
1447; CHECK-NEXT:    [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 poison, i32 poison>
1448; CHECK-NEXT:    ret <4 x double> [[S3]]
1449;
1450  %s1 = shufflevector <2 x double> %x, <2 x double> poison, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef>
1451  %s2 = shufflevector <3 x double> %y, <3 x double> poison, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
1452  %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>
1453  ret <4 x double> %s3
1454}
1455
1456; Demanded vector elements may not be able to simplify a shuffle mask
1457; before we try to narrow it. This used to crash.
1458
1459define <4 x float> @insert_subvector_crash_invalid_mask_elt(<2 x float> %x, ptr %p) {
1460; CHECK-LABEL: @insert_subvector_crash_invalid_mask_elt(
1461; CHECK-NEXT:    [[WIDEN:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
1462; CHECK-NEXT:    [[I:%.*]] = shufflevector <2 x float> [[X]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
1463; CHECK-NEXT:    store <4 x float> [[I]], ptr [[P:%.*]], align 16
1464; CHECK-NEXT:    ret <4 x float> [[WIDEN]]
1465;
1466  %widen = shufflevector <2 x float> %x, <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
1467  %ext2 = extractelement <2 x float> %x, i32 0
1468  %I = insertelement <4 x float> %widen, float %ext2, i16 0
1469  store <4 x float> %I, ptr %p
1470  ret <4 x float> %widen
1471}
1472
1473define <4 x i32> @splat_assoc_add(<4 x i32> %x, <4 x i32> %y) {
1474; CHECK-LABEL: @splat_assoc_add(
1475; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 317426, i32 poison, i32 poison, i32 poison>
1476; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1477; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1478; CHECK-NEXT:    ret <4 x i32> [[R]]
1479;
1480  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> zeroinitializer
1481  %a = add <4 x i32> %y, <i32 317426, i32 317426, i32 317426, i32 317426>
1482  %r = add <4 x i32> %splatx, %a
1483  ret <4 x i32> %r
1484}
1485
1486define <vscale x 4 x i32> @vsplat_assoc_add(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
1487; CHECK-LABEL: @vsplat_assoc_add(
1488; CHECK-NEXT:    [[TMP1:%.*]] = add <vscale x 4 x i32> [[X:%.*]], splat (i32 317426)
1489; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
1490; CHECK-NEXT:    [[R:%.*]] = add <vscale x 4 x i32> [[TMP2]], [[Y:%.*]]
1491; CHECK-NEXT:    ret <vscale x 4 x i32> [[R]]
1492;
1493
1494  %splatx = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
1495  %a = add <vscale x 4 x i32> %y, splat (i32 317426)
1496  %r = add <vscale x 4 x i32> %splatx, %a
1497  ret <vscale x 4 x i32> %r
1498}
1499
1500; Undefs in splat mask are replaced with defined splat index
1501
1502define <4 x i32> @splat_assoc_add_undef_mask_elts(<4 x i32> %x, <4 x i32> %y) {
1503; CHECK-LABEL: @splat_assoc_add_undef_mask_elts(
1504; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison>
1505; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1506; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1507; CHECK-NEXT:    ret <4 x i32> [[R]]
1508;
1509  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 undef, i32 undef>
1510  %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1511  %r = add <4 x i32> %splatx, %a
1512  ret <4 x i32> %r
1513}
1514
1515; Undefs in splat mask are replaced with defined splat index
1516
1517define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) {
1518; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index(
1519; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison>
1520; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
1521; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]]
1522; CHECK-NEXT:    ret <4 x i32> [[R]]
1523;
1524  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1525  %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1526  %r = add <4 x i32> %splatx, %a
1527  ret <4 x i32> %r
1528}
1529
1530define <4 x i32> @splat_assoc_add_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1531; CHECK-LABEL: @splat_assoc_add_undef_constant_elts(
1532; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer
1533; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1534; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1535; CHECK-NEXT:    ret <4 x i32> [[R]]
1536;
1537  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> zeroinitializer
1538  %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1539  %r = add <4 x i32> %splatx, %a
1540  ret <4 x i32> %r
1541}
1542
1543define <4 x i32> @splat_assoc_add_undef_constant_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) {
1544; CHECK-LABEL: @splat_assoc_add_undef_constant_elt_at_splat_index(
1545; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer
1546; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42>
1547; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1548; CHECK-NEXT:    ret <4 x i32> [[R]]
1549;
1550  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> zeroinitializer
1551  %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42>
1552  %r = add <4 x i32> %splatx, %a
1553  ret <4 x i32> %r
1554}
1555
1556define <4 x i32> @splat_assoc_add_undef_mask_elts_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1557; CHECK-LABEL: @splat_assoc_add_undef_mask_elts_undef_constant_elts(
1558; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 0, i32 poison, i32 0, i32 poison>
1559; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1560; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1561; CHECK-NEXT:    ret <4 x i32> [[R]]
1562;
1563  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 0, i32 undef, i32 0, i32 undef>
1564  %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1565  %r = add <4 x i32> %splatx, %a
1566  ret <4 x i32> %r
1567}
1568
1569define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) {
1570; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts(
1571; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 0, i32 0>
1572; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42>
1573; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1574; CHECK-NEXT:    ret <4 x i32> [[R]]
1575;
1576  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1577  %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42>
1578  %r = add <4 x i32> %splatx, %a
1579  ret <4 x i32> %r
1580}
1581
1582define <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) {
1583; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elt_at_splat_index(
1584; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 0, i32 0>
1585; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42>
1586; CHECK-NEXT:    [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]]
1587; CHECK-NEXT:    ret <4 x i32> [[R]]
1588;
1589  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
1590  %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42>
1591  %r = add <4 x i32> %splatx, %a
1592  ret <4 x i32> %r
1593}
1594
1595; Non-zero splat index; commute operands; FMF intersect
1596
1597define <2 x float> @splat_assoc_fmul(<2 x float> %x, <2 x float> %y) {
1598; CHECK-LABEL: @splat_assoc_fmul(
1599; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], <float poison, float 3.000000e+00>
1600; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 1>
1601; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP2]], [[Y:%.*]]
1602; CHECK-NEXT:    ret <2 x float> [[R]]
1603;
1604  %splatx = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 1>
1605  %a = fmul reassoc nsz <2 x float> %y, <float 3.0, float 3.0>
1606  %r = fmul reassoc nsz nnan <2 x float> %a, %splatx
1607  ret <2 x float> %r
1608}
1609
1610; Two splat shuffles; drop poison-generating flags
1611
1612define <3 x i8> @splat_assoc_mul(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1613; CHECK-LABEL: @splat_assoc_mul(
1614; CHECK-NEXT:    [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]]
1615; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1616; CHECK-NEXT:    [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1617; CHECK-NEXT:    ret <3 x i8> [[R]]
1618;
1619  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1620  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1621  %a = mul nsw <3 x i8> %y, %splatz
1622  %r = mul <3 x i8> %a, %splatx
1623  ret <3 x i8> %r
1624}
1625
1626define <3 x i8> @splat_assoc_mul_undef_elt1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1627; CHECK-LABEL: @splat_assoc_mul_undef_elt1(
1628; CHECK-NEXT:    [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]]
1629; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1630; CHECK-NEXT:    [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1631; CHECK-NEXT:    ret <3 x i8> [[R]]
1632;
1633  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 undef, i32 2, i32 2>
1634  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1635  %a = mul nsw <3 x i8> %y, %splatz
1636  %r = mul nsw nuw <3 x i8> %a, %splatx
1637  ret <3 x i8> %r
1638}
1639
1640define <3 x i8> @splat_assoc_mul_undef_elt2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1641; CHECK-LABEL: @splat_assoc_mul_undef_elt2(
1642; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1643; CHECK-NEXT:    [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 poison, i32 2, i32 2>
1644; CHECK-NEXT:    [[A:%.*]] = mul nsw <3 x i8> [[Y:%.*]], [[SPLATZ]]
1645; CHECK-NEXT:    [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]]
1646; CHECK-NEXT:    ret <3 x i8> [[R]]
1647;
1648  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1649  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 undef, i32 2, i32 2>
1650  %a = mul nsw <3 x i8> %y, %splatz
1651  %r = mul nsw nuw <3 x i8> %a, %splatx
1652  ret <3 x i8> %r
1653}
1654
1655define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1656; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index1(
1657; CHECK-NEXT:    [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]]
1658; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1659; CHECK-NEXT:    [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]]
1660; CHECK-NEXT:    ret <3 x i8> [[R]]
1661;
1662  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 undef>
1663  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1664  %a = mul nsw <3 x i8> %y, %splatz
1665  %r = mul nsw nuw <3 x i8> %a, %splatx
1666  ret <3 x i8> %r
1667}
1668
1669define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1670; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index2(
1671; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1672; CHECK-NEXT:    [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 poison>
1673; CHECK-NEXT:    [[A:%.*]] = mul nsw <3 x i8> [[Y:%.*]], [[SPLATZ]]
1674; CHECK-NEXT:    [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]]
1675; CHECK-NEXT:    ret <3 x i8> [[R]]
1676;
1677  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1678  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 undef>
1679  %a = mul nsw <3 x i8> %y, %splatz
1680  %r = mul nsw nuw <3 x i8> %a, %splatx
1681  ret <3 x i8> %r
1682}
1683
1684; Negative test - mismatched splat elements
1685
1686define <3 x i8> @splat_assoc_or(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
1687; CHECK-LABEL: @splat_assoc_or(
1688; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 1, i32 1>
1689; CHECK-NEXT:    [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1690; CHECK-NEXT:    [[A:%.*]] = or <3 x i8> [[Y:%.*]], [[SPLATZ]]
1691; CHECK-NEXT:    [[R:%.*]] = or <3 x i8> [[A]], [[SPLATX]]
1692; CHECK-NEXT:    ret <3 x i8> [[R]]
1693;
1694  %splatx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 1, i32 1>
1695  %splatz = shufflevector <3 x i8> %z, <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2>
1696  %a = or <3 x i8> %y, %splatz
1697  %r = or <3 x i8> %a, %splatx
1698  ret <3 x i8> %r
1699}
1700
1701; Negative test - not associative
1702
1703define <2 x float> @splat_assoc_fdiv(<2 x float> %x, <2 x float> %y) {
1704; CHECK-LABEL: @splat_assoc_fdiv(
1705; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
1706; CHECK-NEXT:    [[A:%.*]] = fdiv reassoc nsz <2 x float> [[Y:%.*]], splat (float 3.000000e+00)
1707; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz <2 x float> [[A]], [[SPLATX]]
1708; CHECK-NEXT:    ret <2 x float> [[R]]
1709;
1710  %splatx = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer
1711  %a = fdiv reassoc nsz <2 x float> %y, <float 3.0, float 3.0>
1712  %r = fdiv reassoc nsz <2 x float> %a, %splatx
1713  ret <2 x float> %r
1714}
1715
1716; Negative test - extra use
1717
1718define <2 x float> @splat_assoc_fadd(<2 x float> %x, <2 x float> %y) {
1719; CHECK-LABEL: @splat_assoc_fadd(
1720; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 1>
1721; CHECK-NEXT:    [[A:%.*]] = fadd fast <2 x float> [[Y:%.*]], splat (float 3.000000e+00)
1722; CHECK-NEXT:    call void @use(<2 x float> [[A]])
1723; CHECK-NEXT:    [[R:%.*]] = fadd fast <2 x float> [[A]], [[SPLATX]]
1724; CHECK-NEXT:    ret <2 x float> [[R]]
1725;
1726  %splatx = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 1>
1727  %a = fadd fast <2 x float> %y, <float 3.0, float 3.0>
1728  call void @use(<2 x float> %a)
1729  %r = fadd fast <2 x float> %a, %splatx
1730  ret <2 x float> %r
1731}
1732
1733; Negative test - narrowing splat
1734
1735define <3 x i32> @splat_assoc_and(<4 x i32> %x, <3 x i32> %y) {
1736; CHECK-LABEL: @splat_assoc_and(
1737; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <3 x i32> zeroinitializer
1738; CHECK-NEXT:    [[A:%.*]] = and <3 x i32> [[Y:%.*]], splat (i32 42)
1739; CHECK-NEXT:    [[R:%.*]] = and <3 x i32> [[SPLATX]], [[A]]
1740; CHECK-NEXT:    ret <3 x i32> [[R]]
1741;
1742  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <3 x i32> zeroinitializer
1743  %a = and <3 x i32> %y, <i32 42, i32 42, i32 42>
1744  %r = and <3 x i32> %splatx, %a
1745  ret <3 x i32> %r
1746}
1747
1748; Negative test - widening splat
1749
1750define <5 x i32> @splat_assoc_xor(<4 x i32> %x, <5 x i32> %y) {
1751; CHECK-LABEL: @splat_assoc_xor(
1752; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <5 x i32> zeroinitializer
1753; CHECK-NEXT:    [[TMP1:%.*]] = xor <5 x i32> [[Y:%.*]], [[SPLATX]]
1754; CHECK-NEXT:    [[R:%.*]] = xor <5 x i32> [[TMP1]], splat (i32 42)
1755; CHECK-NEXT:    ret <5 x i32> [[R]]
1756;
1757  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <5 x i32> zeroinitializer
1758  %a = xor <5 x i32> %y, <i32 42, i32 42, i32 42, i32 42, i32 42>
1759  %r = xor <5 x i32> %splatx, %a
1760  ret <5 x i32> %r
1761}
1762
1763; Negative test - opcode mismatch
1764
1765define <4 x i32> @splat_assoc_add_mul(<4 x i32> %x, <4 x i32> %y) {
1766; CHECK-LABEL: @splat_assoc_add_mul(
1767; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer
1768; CHECK-NEXT:    [[A:%.*]] = add <4 x i32> [[Y:%.*]], splat (i32 42)
1769; CHECK-NEXT:    [[R:%.*]] = mul <4 x i32> [[SPLATX]], [[A]]
1770; CHECK-NEXT:    ret <4 x i32> [[R]]
1771;
1772  %splatx = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> zeroinitializer
1773  %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42>
1774  %r = mul <4 x i32> %splatx, %a
1775  ret <4 x i32> %r
1776}
1777
1778
1779; Do not crash on constant expressions.
1780
1781define <4 x i32> @PR46872(<4 x i32> %x) {
1782; CHECK-LABEL: @PR46872(
1783; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 1, i32 1>
1784; CHECK-NEXT:    [[A:%.*]] = and <4 x i32> [[S]], bitcast (<2 x i64> <i64 ptrtoint (ptr @PR46872 to i64), i64 ptrtoint (ptr @PR46872 to i64)> to <4 x i32>)
1785; CHECK-NEXT:    ret <4 x i32> [[A]]
1786;
1787  %s = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 undef, i32 0, i32 1, i32 1>
1788  %a = and <4 x i32> %s, bitcast (<2 x i64> <i64 ptrtoint (ptr @PR46872 to i64), i64 ptrtoint (ptr @PR46872 to i64)> to <4 x i32>)
1789  ret <4 x i32> %a
1790}
1791
1792