Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / shuffle_select-inseltpoison.ll
blobf573ff36d2cea4cef20a86924da983be620d8c93
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Try to eliminate binops and shuffles when the shuffle is a select in disguise:
5 ; PR37806 - https://bugs.llvm.org/show_bug.cgi?id=37806
7 define <4 x i32> @add(<4 x i32> %v) {
8 ; CHECK-LABEL: @add(
9 ; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 13, i32 0>
10 ; CHECK-NEXT:    ret <4 x i32> [[S]]
12   %b = add <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
13   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
14   ret <4 x i32> %s
17 ; Propagate flags when possible.
19 define <4 x i32> @add_nuw_nsw(<4 x i32> %v) {
20 ; CHECK-LABEL: @add_nuw_nsw(
21 ; CHECK-NEXT:    [[S:%.*]] = add nuw nsw <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 13, i32 0>
22 ; CHECK-NEXT:    ret <4 x i32> [[S]]
24   %b = add nuw nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
25   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
26   ret <4 x i32> %s
29 define <4 x i32> @add_undef_mask_elt(<4 x i32> %v) {
30 ; CHECK-LABEL: @add_undef_mask_elt(
31 ; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 undef, i32 0>
32 ; CHECK-NEXT:    ret <4 x i32> [[S]]
34   %b = add <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
35   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>
36   ret <4 x i32> %s
39 ; Poison flags must be dropped or undef must be replaced with safe constant.
41 define <4 x i32> @add_nuw_nsw_undef_mask_elt(<4 x i32> %v) {
42 ; CHECK-LABEL: @add_nuw_nsw_undef_mask_elt(
43 ; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 undef, i32 13, i32 0>
44 ; CHECK-NEXT:    ret <4 x i32> [[S]]
46   %b = add nuw nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
47   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>
48   ret <4 x i32> %s
51 ; Constant operand 0 (LHS) could work for some non-commutative binops?
53 define <4 x i32> @sub(<4 x i32> %v) {
54 ; CHECK-LABEL: @sub(
55 ; CHECK-NEXT:    [[B:%.*]] = sub <4 x i32> <i32 poison, i32 poison, i32 poison, i32 14>, [[V:%.*]]
56 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
57 ; CHECK-NEXT:    ret <4 x i32> [[S]]
59   %b = sub <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
60   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
61   ret <4 x i32> %s
64 ; If any element of the shuffle mask operand is undef, that element of the result is undef.
65 ; The shuffle is eliminated in this transform, but we can replace a constant element with undef.
66 ; Preserve flags when possible. It's not safe to propagate poison-generating flags with undef constants.
68 define <4 x i32> @mul(<4 x i32> %v) {
69 ; CHECK-LABEL: @mul(
70 ; CHECK-NEXT:    [[S:%.*]] = mul <4 x i32> [[V:%.*]], <i32 undef, i32 12, i32 1, i32 14>
71 ; CHECK-NEXT:    ret <4 x i32> [[S]]
73   %b = mul nsw nuw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
74   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>
75   ret <4 x i32> %s
78 define <4 x i32> @shl(<4 x i32> %v) {
79 ; CHECK-LABEL: @shl(
80 ; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>
81 ; CHECK-NEXT:    ret <4 x i32> [[S]]
83   %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
84   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 1, i32 2, i32 7>
85   ret <4 x i32> %s
88 define <4 x i32> @shl_nsw(<4 x i32> %v) {
89 ; CHECK-LABEL: @shl_nsw(
90 ; CHECK-NEXT:    [[S:%.*]] = shl nsw <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>
91 ; CHECK-NEXT:    ret <4 x i32> [[S]]
93   %b = shl nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
94   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 1, i32 2, i32 7>
95   ret <4 x i32> %s
98 define <4 x i32> @shl_undef_mask_elt(<4 x i32> %v) {
99 ; CHECK-LABEL: @shl_undef_mask_elt(
100 ; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>
101 ; CHECK-NEXT:    ret <4 x i32> [[S]]
103   %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
104   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
105   ret <4 x i32> %s
108 define <4 x i32> @shl_nuw_undef_mask_elt(<4 x i32> %v) {
109 ; CHECK-LABEL: @shl_nuw_undef_mask_elt(
110 ; CHECK-NEXT:    [[S:%.*]] = shl nuw <4 x i32> [[V:%.*]], <i32 0, i32 0, i32 13, i32 0>
111 ; CHECK-NEXT:    ret <4 x i32> [[S]]
113   %b = shl nuw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
114   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
115   ret <4 x i32> %s
118 define <4 x i32> @lshr_constant_op0(<4 x i32> %v) {
119 ; CHECK-LABEL: @lshr_constant_op0(
120 ; CHECK-NEXT:    [[S:%.*]] = lshr <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 0, i32 14>
121 ; CHECK-NEXT:    ret <4 x i32> [[S]]
123   %b = lshr <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
124   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
125   ret <4 x i32> %s
128 define <4 x i32> @lshr_exact_constant_op0(<4 x i32> %v) {
129 ; CHECK-LABEL: @lshr_exact_constant_op0(
130 ; CHECK-NEXT:    [[S:%.*]] = lshr exact <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 0, i32 14>
131 ; CHECK-NEXT:    ret <4 x i32> [[S]]
133   %b = lshr exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
134   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
135   ret <4 x i32> %s
138 define <4 x i32> @lshr_undef_mask_elt(<4 x i32> %v) {
139 ; CHECK-LABEL: @lshr_undef_mask_elt(
140 ; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>
141 ; CHECK-NEXT:    ret <4 x i32> [[S]]
143   %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
144   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
145   ret <4 x i32> %s
148 define <4 x i32> @lshr_exact_undef_mask_elt(<4 x i32> %v) {
149 ; CHECK-LABEL: @lshr_exact_undef_mask_elt(
150 ; CHECK-NEXT:    [[S:%.*]] = lshr exact <4 x i32> [[V:%.*]], <i32 0, i32 0, i32 13, i32 0>
151 ; CHECK-NEXT:    ret <4 x i32> [[S]]
153   %b = lshr exact  <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
154   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
155   ret <4 x i32> %s
158 define <4 x i32> @lshr_constant_op1(<4 x i32> %v) {
159 ; CHECK-LABEL: @lshr_constant_op1(
160 ; CHECK-NEXT:    [[B:%.*]] = lshr exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
161 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
162 ; CHECK-NEXT:    ret <4 x i32> [[S]]
164   %b = lshr exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
165   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
166   ret <4 x i32> %s
169 ; Try weird types.
171 define <3 x i32> @ashr(<3 x i32> %v) {
172 ; CHECK-LABEL: @ashr(
173 ; CHECK-NEXT:    [[S:%.*]] = ashr <3 x i32> [[V:%.*]], <i32 0, i32 12, i32 13>
174 ; CHECK-NEXT:    ret <3 x i32> [[S]]
176   %b = ashr <3 x i32> %v, <i32 11, i32 12, i32 13>
177   %s = shufflevector <3 x i32> %b, <3 x i32> %v, <3 x i32> <i32 3, i32 1, i32 2>
178   ret <3 x i32> %s
181 define <3 x i42> @and(<3 x i42> %v) {
182 ; CHECK-LABEL: @and(
183 ; CHECK-NEXT:    [[S:%.*]] = and <3 x i42> [[V:%.*]], <i42 -1, i42 12, i42 undef>
184 ; CHECK-NEXT:    ret <3 x i42> [[S]]
186   %b = and <3 x i42> %v, <i42 11, i42 12, i42 13>
187   %s = shufflevector <3 x i42> %v, <3 x i42> %b, <3 x i32> <i32 0, i32 4, i32 undef>
188   ret <3 x i42> %s
191 ; It doesn't matter if the intermediate op has extra uses.
193 declare void @use_v4i32(<4 x i32>)
195 define <4 x i32> @or(<4 x i32> %v) {
196 ; CHECK-LABEL: @or(
197 ; CHECK-NEXT:    [[B:%.*]] = or <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 13, i32 14>
198 ; CHECK-NEXT:    [[S:%.*]] = or <4 x i32> [[V]], <i32 0, i32 0, i32 13, i32 14>
199 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[B]])
200 ; CHECK-NEXT:    ret <4 x i32> [[S]]
202   %b = or <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
203   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
204   call void @use_v4i32(<4 x i32> %b)
205   ret <4 x i32> %s
208 define <4 x i32> @xor(<4 x i32> %v) {
209 ; CHECK-LABEL: @xor(
210 ; CHECK-NEXT:    [[S:%.*]] = xor <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 0, i32 0>
211 ; CHECK-NEXT:    ret <4 x i32> [[S]]
213   %b = xor <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
214   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
215   ret <4 x i32> %s
218 define <4 x i32> @udiv(<4 x i32> %v) {
219 ; CHECK-LABEL: @udiv(
220 ; CHECK-NEXT:    [[B:%.*]] = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
221 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
222 ; CHECK-NEXT:    ret <4 x i32> [[S]]
224   %b = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
225   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
226   ret <4 x i32> %s
229 define <4 x i32> @udiv_exact(<4 x i32> %v) {
230 ; CHECK-LABEL: @udiv_exact(
231 ; CHECK-NEXT:    [[B:%.*]] = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
232 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
233 ; CHECK-NEXT:    ret <4 x i32> [[S]]
235   %b = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
236   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
237   ret <4 x i32> %s
240 define <4 x i32> @udiv_undef_mask_elt(<4 x i32> %v) {
241 ; CHECK-LABEL: @udiv_undef_mask_elt(
242 ; CHECK-NEXT:    [[B:%.*]] = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
243 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>
244 ; CHECK-NEXT:    ret <4 x i32> [[S]]
246   %b = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
247   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>
248   ret <4 x i32> %s
251 define <4 x i32> @udiv_exact_undef_mask_elt(<4 x i32> %v) {
252 ; CHECK-LABEL: @udiv_exact_undef_mask_elt(
253 ; CHECK-NEXT:    [[B:%.*]] = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
254 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>
255 ; CHECK-NEXT:    ret <4 x i32> [[S]]
257   %b = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
258   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>
259   ret <4 x i32> %s
262 define <4 x i32> @sdiv(<4 x i32> %v) {
263 ; CHECK-LABEL: @sdiv(
264 ; CHECK-NEXT:    [[S:%.*]] = sdiv <4 x i32> [[V:%.*]], <i32 11, i32 1, i32 13, i32 1>
265 ; CHECK-NEXT:    ret <4 x i32> [[S]]
267   %b = sdiv <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
268   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
269   ret <4 x i32> %s
272 define <4 x i32> @sdiv_exact(<4 x i32> %v) {
273 ; CHECK-LABEL: @sdiv_exact(
274 ; CHECK-NEXT:    [[S:%.*]] = sdiv exact <4 x i32> [[V:%.*]], <i32 11, i32 1, i32 13, i32 1>
275 ; CHECK-NEXT:    ret <4 x i32> [[S]]
277   %b = sdiv exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
278   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
279   ret <4 x i32> %s
282 ; Div/rem need special handling if the shuffle has undef elements.
284 define <4 x i32> @sdiv_undef_mask_elt(<4 x i32> %v) {
285 ; CHECK-LABEL: @sdiv_undef_mask_elt(
286 ; CHECK-NEXT:    [[S:%.*]] = sdiv <4 x i32> [[V:%.*]], <i32 1, i32 1, i32 13, i32 1>
287 ; CHECK-NEXT:    ret <4 x i32> [[S]]
289   %b = sdiv <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
290   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>
291   ret <4 x i32> %s
294 define <4 x i32> @sdiv_exact_undef_mask_elt(<4 x i32> %v) {
295 ; CHECK-LABEL: @sdiv_exact_undef_mask_elt(
296 ; CHECK-NEXT:    [[S:%.*]] = sdiv exact <4 x i32> [[V:%.*]], <i32 1, i32 1, i32 13, i32 1>
297 ; CHECK-NEXT:    ret <4 x i32> [[S]]
299   %b = sdiv exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>
300   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>
301   ret <4 x i32> %s
304 define <4 x i32> @urem(<4 x i32> %v) {
305 ; CHECK-LABEL: @urem(
306 ; CHECK-NEXT:    [[B:%.*]] = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
307 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
308 ; CHECK-NEXT:    ret <4 x i32> [[S]]
310   %b = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
311   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
312   ret <4 x i32> %s
315 define <4 x i32> @urem_undef_mask_elt(<4 x i32> %v) {
316 ; CHECK-LABEL: @urem_undef_mask_elt(
317 ; CHECK-NEXT:    [[B:%.*]] = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
318 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>
319 ; CHECK-NEXT:    ret <4 x i32> [[S]]
321   %b = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
322   %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>
323   ret <4 x i32> %s
326 define <4 x i32> @srem(<4 x i32> %v) {
327 ; CHECK-LABEL: @srem(
328 ; CHECK-NEXT:    [[B:%.*]] = srem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]
329 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
330 ; CHECK-NEXT:    ret <4 x i32> [[S]]
332   %b = srem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v
333   %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 1, i32 6, i32 3>
334   ret <4 x i32> %s
337 ; Try FP ops/types.
339 define <4 x float> @fadd_maybe_nan(<4 x float> %v) {
340 ; CHECK-LABEL: @fadd_maybe_nan(
341 ; CHECK-NEXT:    [[B:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float poison, float poison>
342 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
343 ; CHECK-NEXT:    ret <4 x float> [[S]]
345   %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
346   %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
347   ret <4 x float> %s
350 define <4 x float> @fadd(<4 x float> nofpclass(nan) %v) {
351 ; CHECK-LABEL: @fadd(
352 ; CHECK-NEXT:    [[S:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float -0.000000e+00, float -0.000000e+00>
353 ; CHECK-NEXT:    ret <4 x float> [[S]]
355   %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
356   %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
357   ret <4 x float> %s
360 define <4 x double> @fsub(<4 x double> %v) {
361 ; CHECK-LABEL: @fsub(
362 ; CHECK-NEXT:    [[B:%.*]] = fsub <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]
363 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[V]], <4 x double> [[B]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>
364 ; CHECK-NEXT:    ret <4 x double> [[S]]
366   %b = fsub <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v
367   %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
368   ret <4 x double> %s
371 ; Propagate any FMF.
373 define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {
374 ; CHECK-LABEL: @fmul(
375 ; CHECK-NEXT:    [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
376 ; CHECK-NEXT:    ret <4 x float> [[S]]
378   %b = fmul nnan ninf <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
379   %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
380   ret <4 x float> %s
383 define <4 x double> @fdiv_constant_op0(<4 x double> %v) {
384 ; CHECK-LABEL: @fdiv_constant_op0(
385 ; CHECK-NEXT:    [[B:%.*]] = fdiv fast <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]
386 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[V]], <4 x double> [[B]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>
387 ; CHECK-NEXT:    ret <4 x double> [[S]]
389   %b = fdiv fast <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v
390   %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
391   ret <4 x double> %s
394 define <4 x double> @fdiv_constant_op1(<4 x double> nofpclass(nan) %v) {
395 ; CHECK-LABEL: @fdiv_constant_op1(
396 ; CHECK-NEXT:    [[S:%.*]] = fdiv reassoc <4 x double> [[V:%.*]], <double undef, double 1.000000e+00, double 4.300000e+01, double 4.400000e+01>
397 ; CHECK-NEXT:    ret <4 x double> [[S]]
399   %b = fdiv reassoc <4 x double> %v, <double 41.0, double 42.0, double 43.0, double 44.0>
400   %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
401   ret <4 x double> %s
404 define <4 x double> @frem(<4 x double> %v) {
405 ; CHECK-LABEL: @frem(
406 ; CHECK-NEXT:    [[B:%.*]] = frem <4 x double> <double 4.100000e+01, double 4.200000e+01, double poison, double poison>, [[V:%.*]]
407 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[B]], <4 x double> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
408 ; CHECK-NEXT:    ret <4 x double> [[S]]
410   %b = frem <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v
411   %s = shufflevector <4 x double> %b, <4 x double> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
412   ret <4 x double> %s
415 ; Tests where both operands of the shuffle are binops with the same opcode.
417 define <4 x i32> @add_add(<4 x i32> %v0) {
418 ; CHECK-LABEL: @add_add(
419 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 3, i32 8>
420 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
422   %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
423   %t2 = add <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
424   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
425   ret <4 x i32> %t3
428 define <4 x i32> @add_add_nsw(<4 x i32> %v0) {
429 ; CHECK-LABEL: @add_add_nsw(
430 ; CHECK-NEXT:    [[T3:%.*]] = add nsw <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 3, i32 8>
431 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
433   %t1 = add nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
434   %t2 = add nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
435   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
436   ret <4 x i32> %t3
439 define <4 x i32> @add_add_undef_mask_elt(<4 x i32> %v0) {
440 ; CHECK-LABEL: @add_add_undef_mask_elt(
441 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 undef, i32 8>
442 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
444   %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
445   %t2 = add <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
446   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>
447   ret <4 x i32> %t3
450 ; Poison flags must be dropped or undef must be replaced with safe constant.
452 define <4 x i32> @add_add_nsw_undef_mask_elt(<4 x i32> %v0) {
453 ; CHECK-LABEL: @add_add_nsw_undef_mask_elt(
454 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 undef, i32 8>
455 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
457   %t1 = add nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
458   %t2 = add nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
459   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>
460   ret <4 x i32> %t3
463 ; Constant operand 0 (LHS) also works.
465 define <4 x i32> @sub_sub(<4 x i32> %v0) {
466 ; CHECK-LABEL: @sub_sub(
467 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0:%.*]]
468 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
470   %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
471   %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
472   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
473   ret <4 x i32> %t3
476 define <4 x i32> @sub_sub_nuw(<4 x i32> %v0) {
477 ; CHECK-LABEL: @sub_sub_nuw(
478 ; CHECK-NEXT:    [[T3:%.*]] = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0:%.*]]
479 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
481   %t1 = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
482   %t2 = sub nuw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
483   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
484   ret <4 x i32> %t3
487 define <4 x i32> @sub_sub_undef_mask_elt(<4 x i32> %v0) {
488 ; CHECK-LABEL: @sub_sub_undef_mask_elt(
489 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[V0:%.*]]
490 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
492   %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
493   %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
494   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
495   ret <4 x i32> %t3
498 ; Poison flags must be dropped or undef must be replaced with safe constant.
500 define <4 x i32> @sub_sub_nuw_undef_mask_elt(<4 x i32> %v0) {
501 ; CHECK-LABEL: @sub_sub_nuw_undef_mask_elt(
502 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[V0:%.*]]
503 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
505   %t1 = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
506   %t2 = sub nuw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
507   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
508   ret <4 x i32> %t3
511 ; If any element of the shuffle mask operand is undef, that element of the result is undef.
512 ; The shuffle is eliminated in this transform, but we can replace a constant element with undef.
514 define <4 x i32> @mul_mul(<4 x i32> %v0) {
515 ; CHECK-LABEL: @mul_mul(
516 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[V0:%.*]], <i32 undef, i32 6, i32 3, i32 8>
517 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
519   %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
520   %t2 = mul <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
521   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>
522   ret <4 x i32> %t3
525 ; Preserve flags when possible.
527 define <4 x i32> @shl_shl(<4 x i32> %v0) {
528 ; CHECK-LABEL: @shl_shl(
529 ; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 3, i32 4>
530 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
532   %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
533   %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
534   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
535   ret <4 x i32> %t3
538 define <4 x i32> @shl_shl_nuw(<4 x i32> %v0) {
539 ; CHECK-LABEL: @shl_shl_nuw(
540 ; CHECK-NEXT:    [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 3, i32 4>
541 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
543   %t1 = shl nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
544   %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
545   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
546   ret <4 x i32> %t3
549 ; Shift by undef is poison. Undef must be replaced by safe constant.
551 define <4 x i32> @shl_shl_undef_mask_elt(<4 x i32> %v0) {
552 ; CHECK-LABEL: @shl_shl_undef_mask_elt(
553 ; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 3, i32 0>
554 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
556   %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
557   %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
558   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
559   ret <4 x i32> %t3
562 ; Shift by undef is poison. Undef must be replaced by safe constant.
564 define <4 x i32> @shl_shl_nuw_undef_mask_elt(<4 x i32> %v0) {
565 ; CHECK-LABEL: @shl_shl_nuw_undef_mask_elt(
566 ; CHECK-NEXT:    [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 3, i32 0>
567 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
569   %t1 = shl nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
570   %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
571   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
572   ret <4 x i32> %t3
575 ; Can't propagate the flag here.
577 define <4 x i32> @lshr_lshr(<4 x i32> %v0) {
578 ; CHECK-LABEL: @lshr_lshr(
579 ; CHECK-NEXT:    [[T3:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[V0:%.*]]
580 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
582   %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
583   %t2 = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
584   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
585   ret <4 x i32> %t3
588 ; Try weird types.
590 define <3 x i32> @ashr_ashr(<3 x i32> %v0) {
591 ; CHECK-LABEL: @ashr_ashr(
592 ; CHECK-NEXT:    [[T3:%.*]] = ashr <3 x i32> [[V0:%.*]], <i32 4, i32 2, i32 3>
593 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
595   %t1 = ashr <3 x i32> %v0, <i32 1, i32 2, i32 3>
596   %t2 = ashr <3 x i32> %v0, <i32 4, i32 5, i32 6>
597   %t3 = shufflevector <3 x i32> %t1, <3 x i32> %t2, <3 x i32> <i32 3, i32 1, i32 2>
598   ret <3 x i32> %t3
601 define <3 x i42> @and_and(<3 x i42> %v0) {
602 ; CHECK-LABEL: @and_and(
603 ; CHECK-NEXT:    [[T3:%.*]] = and <3 x i42> [[V0:%.*]], <i42 1, i42 5, i42 undef>
604 ; CHECK-NEXT:    ret <3 x i42> [[T3]]
606   %t1 = and <3 x i42> %v0, <i42 1, i42 2, i42 3>
607   %t2 = and <3 x i42> %v0, <i42 4, i42 5, i42 6>
608   %t3 = shufflevector <3 x i42> %t1, <3 x i42> %t2, <3 x i32> <i32 0, i32 4, i32 undef>
609   ret <3 x i42> %t3
612 ; It doesn't matter if the intermediate ops have extra uses.
614 define <4 x i32> @or_or(<4 x i32> %v0) {
615 ; CHECK-LABEL: @or_or(
616 ; CHECK-NEXT:    [[T1:%.*]] = or <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>
617 ; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[V0]], <i32 5, i32 6, i32 3, i32 4>
618 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])
619 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
621   %t1 = or <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
622   %t2 = or <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
623   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
624   call void @use_v4i32(<4 x i32> %t1)
625   ret <4 x i32> %t3
628 define <4 x i32> @xor_xor(<4 x i32> %v0) {
629 ; CHECK-LABEL: @xor_xor(
630 ; CHECK-NEXT:    [[T2:%.*]] = xor <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 7, i32 8>
631 ; CHECK-NEXT:    [[T3:%.*]] = xor <4 x i32> [[V0]], <i32 1, i32 6, i32 3, i32 4>
632 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])
633 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
635   %t1 = xor <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
636   %t2 = xor <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
637   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
638   call void @use_v4i32(<4 x i32> %t2)
639   ret <4 x i32> %t3
642 define <4 x i32> @udiv_udiv(<4 x i32> %v0) {
643 ; CHECK-LABEL: @udiv_udiv(
644 ; CHECK-NEXT:    [[T1:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
645 ; CHECK-NEXT:    [[T2:%.*]] = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V0]]
646 ; CHECK-NEXT:    [[T3:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0]]
647 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])
648 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])
649 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
651   %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
652   %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
653   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
654   call void @use_v4i32(<4 x i32> %t1)
655   call void @use_v4i32(<4 x i32> %t2)
656   ret <4 x i32> %t3
659 ; Div/rem need special handling if the shuffle has undef elements.
661 define <4 x i32> @sdiv_sdiv(<4 x i32> %v0) {
662 ; CHECK-LABEL: @sdiv_sdiv(
663 ; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 8>
664 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
666   %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
667   %t2 = sdiv <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
668   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
669   ret <4 x i32> %t3
672 define <4 x i32> @sdiv_sdiv_exact(<4 x i32> %v0) {
673 ; CHECK-LABEL: @sdiv_sdiv_exact(
674 ; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 8>
675 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
677   %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
678   %t2 = sdiv exact <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
679   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
680   ret <4 x i32> %t3
683 define <4 x i32> @sdiv_sdiv_undef_mask_elt(<4 x i32> %v0) {
684 ; CHECK-LABEL: @sdiv_sdiv_undef_mask_elt(
685 ; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 1>
686 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
688   %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
689   %t2 = sdiv <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
690   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>
691   ret <4 x i32> %t3
694 define <4 x i32> @sdiv_sdiv_exact_undef_mask_elt(<4 x i32> %v0) {
695 ; CHECK-LABEL: @sdiv_sdiv_exact_undef_mask_elt(
696 ; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 1>
697 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
699   %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
700   %t2 = sdiv exact <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
701   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>
702   ret <4 x i32> %t3
705 define <4 x i32> @urem_urem(<4 x i32> %v0) {
706 ; CHECK-LABEL: @urem_urem(
707 ; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 8>, [[V0:%.*]]
708 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
710   %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
711   %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
712   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
713   ret <4 x i32> %t3
716 ; This is folded by using a safe constant.
718 define <4 x i32> @urem_urem_undef_mask_elt(<4 x i32> %v0) {
719 ; CHECK-LABEL: @urem_urem_undef_mask_elt(
720 ; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 0>, [[V0:%.*]]
721 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
723   %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
724   %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
725   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>
726   ret <4 x i32> %t3
729 define <4 x i32> @srem_srem(<4 x i32> %v0) {
730 ; CHECK-LABEL: @srem_srem(
731 ; CHECK-NEXT:    [[T3:%.*]] = srem <4 x i32> <i32 1, i32 2, i32 7, i32 4>, [[V0:%.*]]
732 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
734   %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
735   %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
736   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>
737   ret <4 x i32> %t3
740 ; This is folded by using a safe constant.
742 define <4 x i32> @srem_srem_undef_mask_elt(<4 x i32> %v0) {
743 ; CHECK-LABEL: @srem_srem_undef_mask_elt(
744 ; CHECK-NEXT:    [[T3:%.*]] = srem <4 x i32> <i32 1, i32 0, i32 7, i32 4>, [[V0:%.*]]
745 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
747   %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
748   %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0
749   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 6, i32 3>
750   ret <4 x i32> %t3
753 ; Try FP ops/types.
755 define <4 x float> @fadd_fadd(<4 x float> %v0) {
756 ; CHECK-LABEL: @fadd_fadd(
757 ; CHECK-NEXT:    [[T3:%.*]] = fadd <4 x float> [[V0:%.*]], <float 1.000000e+00, float 2.000000e+00, float 7.000000e+00, float 8.000000e+00>
758 ; CHECK-NEXT:    ret <4 x float> [[T3]]
760   %t1 = fadd <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>
761   %t2 = fadd <4 x float> %v0, <float 5.0, float 6.0, float 7.0, float 8.0>
762   %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
763   ret <4 x float> %t3
766 define <4 x double> @fsub_fsub(<4 x double> %v0) {
767 ; CHECK-LABEL: @fsub_fsub(
768 ; CHECK-NEXT:    [[T3:%.*]] = fsub <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[V0:%.*]]
769 ; CHECK-NEXT:    ret <4 x double> [[T3]]
771   %t1 = fsub <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
772   %t2 = fsub <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v0
773   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
774   ret <4 x double> %t3
777 ; Intersect any FMF.
779 define <4 x float> @fmul_fmul(<4 x float> %v0) {
780 ; CHECK-LABEL: @fmul_fmul(
781 ; CHECK-NEXT:    [[T3:%.*]] = fmul nnan ninf <4 x float> [[V0:%.*]], <float 1.000000e+00, float 6.000000e+00, float 7.000000e+00, float 8.000000e+00>
782 ; CHECK-NEXT:    ret <4 x float> [[T3]]
784   %t1 = fmul nnan ninf <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>
785   %t2 = fmul nnan ninf <4 x float> %v0, <float 5.0, float 6.0, float 7.0, float 8.0>
786   %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
787   ret <4 x float> %t3
790 define <4 x double> @fdiv_fdiv(<4 x double> %v0) {
791 ; CHECK-LABEL: @fdiv_fdiv(
792 ; CHECK-NEXT:    [[T3:%.*]] = fdiv arcp <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[V0:%.*]]
793 ; CHECK-NEXT:    ret <4 x double> [[T3]]
795   %t1 = fdiv fast <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
796   %t2 = fdiv nnan arcp <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v0
797   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
798   ret <4 x double> %t3
801 ; The variable operand must be either the first operand or second operand in both binops.
803 define <4 x double> @frem_frem(<4 x double> %v0) {
804 ; CHECK-LABEL: @frem_frem(
805 ; CHECK-NEXT:    [[T1:%.*]] = frem <4 x double> <double 1.000000e+00, double 2.000000e+00, double poison, double poison>, [[V0:%.*]]
806 ; CHECK-NEXT:    [[T2:%.*]] = frem <4 x double> [[V0]], <double poison, double poison, double 7.000000e+00, double 8.000000e+00>
807 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
808 ; CHECK-NEXT:    ret <4 x double> [[T3]]
810   %t1 = frem <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
811   %t2 = frem <4 x double> %v0, <double 5.0, double 6.0, double 7.0, double 8.0>
812   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
813   ret <4 x double> %t3
816 define <4 x i32> @add_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
817 ; CHECK-LABEL: @add_2_vars(
818 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
819 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>
820 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
822   %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
823   %t2 = add <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
824   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
825   ret <4 x i32> %t3
828 ; Constant operand 0 (LHS) also works.
830 define <4 x i32> @sub_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
831 ; CHECK-LABEL: @sub_2_vars(
832 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
833 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[TMP1]]
834 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
836   %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
837   %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
838   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
839   ret <4 x i32> %t3
842 define <4 x i32> @sub_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) {
843 ; CHECK-LABEL: @sub_2_vars_nsw(
844 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
845 ; CHECK-NEXT:    [[T3:%.*]] = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[TMP1]]
846 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
848   %t1 = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
849   %t2 = sub nsw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
850   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
851   ret <4 x i32> %t3
854 define <4 x i32> @sub_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
855 ; CHECK-LABEL: @sub_2_vars_undef_mask_elt(
856 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>
857 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[TMP1]]
858 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
860   %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
861   %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
862   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
863   ret <4 x i32> %t3
866 ; Poison flags must be dropped or undef must be replaced with safe constant.
868 define <4 x i32> @sub_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
869 ; CHECK-LABEL: @sub_2_vars_nsw_undef_mask_elt(
870 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>
871 ; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[TMP1]]
872 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
874   %t1 = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
875   %t2 = sub nsw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
876   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
877   ret <4 x i32> %t3
880 ; If any element of the shuffle mask operand is undef, that element of the result is undef.
881 ; The shuffle is eliminated in this transform, but we can replace a constant element with undef.
883 define <4 x i32> @mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
884 ; CHECK-LABEL: @mul_2_vars(
885 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
886 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>
887 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
889   %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
890   %t2 = mul <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
891   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
892   ret <4 x i32> %t3
895 define <4 x i32> @mul_2_vars_nuw(<4 x i32> %v0, <4 x i32> %v1) {
896 ; CHECK-LABEL: @mul_2_vars_nuw(
897 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
898 ; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>
899 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
901   %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
902   %t2 = mul nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
903   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
904   ret <4 x i32> %t3
907 define <4 x i32> @mul_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
908 ; CHECK-LABEL: @mul_2_vars_undef_mask_elt(
909 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>
910 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 undef, i32 3, i32 8>
911 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
913   %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
914   %t2 = mul <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
915   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>
916   ret <4 x i32> %t3
919 ; Poison flags must be dropped or undef must be replaced with safe constant.
921 define <4 x i32> @mul_2_vars_nuw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
922 ; CHECK-LABEL: @mul_2_vars_nuw_undef_mask_elt(
923 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>
924 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 undef, i32 3, i32 8>
925 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
927   %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
928   %t2 = mul nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
929   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>
930   ret <4 x i32> %t3
933 ; Preserve flags when possible.
935 define <4 x i32> @shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
936 ; CHECK-LABEL: @shl_2_vars(
937 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
938 ; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 4>
939 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
941   %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
942   %t2 = shl <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
943   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
944   ret <4 x i32> %t3
947 define <4 x i32> @shl_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) {
948 ; CHECK-LABEL: @shl_2_vars_nsw(
949 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
950 ; CHECK-NEXT:    [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 4>
951 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
953   %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
954   %t2 = shl nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
955   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
956   ret <4 x i32> %t3
959 ; Shift by undef is poison. Undef is replaced by safe constant.
961 define <4 x i32> @shl_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
962 ; CHECK-LABEL: @shl_2_vars_undef_mask_elt(
963 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 5, i32 2, i32 poison>
964 ; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[TMP1]], <i32 0, i32 6, i32 3, i32 0>
965 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
967   %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
968   %t2 = shl <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
969   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
970   ret <4 x i32> %t3
973 ; Shift by undef is poison. Undef is replaced by safe constant.
975 define <4 x i32> @shl_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
976 ; CHECK-LABEL: @shl_2_vars_nsw_undef_mask_elt(
977 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 5, i32 2, i32 poison>
978 ; CHECK-NEXT:    [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], <i32 0, i32 6, i32 3, i32 0>
979 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
981   %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
982   %t2 = shl nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
983   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>
984   ret <4 x i32> %t3
987 ; Can't propagate the flag here.
989 define <4 x i32> @lshr_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
990 ; CHECK-LABEL: @lshr_2_vars(
991 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
992 ; CHECK-NEXT:    [[T3:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[TMP1]]
993 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
995   %t1 = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
996   %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
997   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
998   ret <4 x i32> %t3
1001 define <4 x i32> @lshr_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {
1002 ; CHECK-LABEL: @lshr_2_vars_exact(
1003 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
1004 ; CHECK-NEXT:    [[T3:%.*]] = lshr exact <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[TMP1]]
1005 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1007   %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1008   %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1009   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
1010   ret <4 x i32> %t3
1013 ; TODO: This would require a new shuffle mask (replace undef with op0 or op1 lane). Otherwise, we have shift-by-undef.
1015 define <4 x i32> @lshr_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1016 ; CHECK-LABEL: @lshr_2_vars_undef_mask_elt(
1017 ; CHECK-NEXT:    [[T1:%.*]] = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1018 ; CHECK-NEXT:    [[T2:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]
1019 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 5, i32 2, i32 7>
1020 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1022   %t1 = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1023   %t2 = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1024   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>
1025   ret <4 x i32> %t3
1028 ; TODO: This would require a new shuffle mask (replace undef with op0 or op1 lane). Otherwise, we have shift-by-undef.
1030 define <4 x i32> @lshr_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1031 ; CHECK-LABEL: @lshr_2_vars_exact_undef_mask_elt(
1032 ; CHECK-NEXT:    [[T1:%.*]] = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1033 ; CHECK-NEXT:    [[T2:%.*]] = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]
1034 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 5, i32 2, i32 7>
1035 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1037   %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1038   %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1039   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>
1040   ret <4 x i32> %t3
1043 ; Try weird types.
1045 define <3 x i32> @ashr_2_vars(<3 x i32> %v0, <3 x i32> %v1) {
1046 ; CHECK-LABEL: @ashr_2_vars(
1047 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i32> [[V1:%.*]], <3 x i32> [[V0:%.*]], <3 x i32> <i32 0, i32 4, i32 5>
1048 ; CHECK-NEXT:    [[T3:%.*]] = ashr <3 x i32> [[TMP1]], <i32 4, i32 2, i32 3>
1049 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
1051   %t1 = ashr <3 x i32> %v0, <i32 1, i32 2, i32 3>
1052   %t2 = ashr <3 x i32> %v1, <i32 4, i32 5, i32 6>
1053   %t3 = shufflevector <3 x i32> %t1, <3 x i32> %t2, <3 x i32> <i32 3, i32 1, i32 2>
1054   ret <3 x i32> %t3
1057 define <3 x i42> @and_2_vars(<3 x i42> %v0, <3 x i42> %v1) {
1058 ; CHECK-LABEL: @and_2_vars(
1059 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i42> [[V0:%.*]], <3 x i42> [[V1:%.*]], <3 x i32> <i32 0, i32 4, i32 poison>
1060 ; CHECK-NEXT:    [[T3:%.*]] = and <3 x i42> [[TMP1]], <i42 1, i42 5, i42 undef>
1061 ; CHECK-NEXT:    ret <3 x i42> [[T3]]
1063   %t1 = and <3 x i42> %v0, <i42 1, i42 2, i42 3>
1064   %t2 = and <3 x i42> %v1, <i42 4, i42 5, i42 6>
1065   %t3 = shufflevector <3 x i42> %t1, <3 x i42> %t2, <3 x i32> <i32 0, i32 4, i32 undef>
1066   ret <3 x i42> %t3
1069 ; It doesn't matter if only one intermediate op has extra uses.
1071 define <4 x i32> @or_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1072 ; CHECK-LABEL: @or_2_vars(
1073 ; CHECK-NEXT:    [[T1:%.*]] = or <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>
1074 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1075 ; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[TMP1]], <i32 5, i32 6, i32 3, i32 4>
1076 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])
1077 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1079   %t1 = or <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1080   %t2 = or <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1081   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1082   call void @use_v4i32(<4 x i32> %t1)
1083   ret <4 x i32> %t3
1086 ; But we don't transform if both intermediate values have extra uses.
1088 define <4 x i32> @xor_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1089 ; CHECK-LABEL: @xor_2_vars(
1090 ; CHECK-NEXT:    [[T1:%.*]] = xor <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>
1091 ; CHECK-NEXT:    [[T2:%.*]] = xor <4 x i32> [[V1:%.*]], <i32 5, i32 6, i32 7, i32 8>
1092 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
1093 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])
1094 ; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])
1095 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1097   %t1 = xor <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1098   %t2 = xor <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1099   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
1100   call void @use_v4i32(<4 x i32> %t1)
1101   call void @use_v4i32(<4 x i32> %t2)
1102   ret <4 x i32> %t3
1105 ; Div/rem need special handling if the shuffle has undef elements.
1107 define <4 x i32> @udiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1108 ; CHECK-LABEL: @udiv_2_vars(
1109 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>
1110 ; CHECK-NEXT:    [[T3:%.*]] = udiv <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]
1111 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1113   %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1114   %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1115   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 1, i32 2, i32 7>
1116   ret <4 x i32> %t3
1119 define <4 x i32> @udiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {
1120 ; CHECK-LABEL: @udiv_2_vars_exact(
1121 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>
1122 ; CHECK-NEXT:    [[T3:%.*]] = udiv exact <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]
1123 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1125   %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1126   %t2 = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1127   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 1, i32 2, i32 7>
1128   ret <4 x i32> %t3
1131 ; TODO: This could be transformed using a safe constant.
1133 define <4 x i32> @udiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1134 ; CHECK-LABEL: @udiv_2_vars_undef_mask_elt(
1135 ; CHECK-NEXT:    [[T1:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1136 ; CHECK-NEXT:    [[T2:%.*]] = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]
1137 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>
1138 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1140   %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1141   %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1142   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
1143   ret <4 x i32> %t3
1146 ; TODO: This could be transformed using a safe constant.
1148 define <4 x i32> @udiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1149 ; CHECK-LABEL: @udiv_2_vars_exact_undef_mask_elt(
1150 ; CHECK-NEXT:    [[T1:%.*]] = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1151 ; CHECK-NEXT:    [[T2:%.*]] = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]
1152 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>
1153 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1155   %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1156   %t2 = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1157   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>
1158   ret <4 x i32> %t3
1161 ; If the shuffle has no undefs, it's safe to shuffle the variables first.
1163 define <4 x i32> @sdiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1164 ; CHECK-LABEL: @sdiv_2_vars(
1165 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
1166 ; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>
1167 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1169   %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1170   %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1171   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>
1172   ret <4 x i32> %t3
1175 define <4 x i32> @sdiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {
1176 ; CHECK-LABEL: @sdiv_2_vars_exact(
1177 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
1178 ; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>
1179 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1181   %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1182   %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1183   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>
1184   ret <4 x i32> %t3
1187 ; Div by undef is UB. Undef is replaced by safe constant.
1189 define <4 x i32> @sdiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1190 ; CHECK-LABEL: @sdiv_2_vars_undef_mask_elt(
1191 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>
1192 ; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>
1193 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1195   %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1196   %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1197   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>
1198   ret <4 x i32> %t3
1201 ; Div by undef is UB. Undef is replaced by safe constant.
1203 define <4 x i32> @sdiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {
1204 ; CHECK-LABEL: @sdiv_2_vars_exact_undef_mask_elt(
1205 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>
1206 ; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>
1207 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1209   %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1210   %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1211   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>
1212   ret <4 x i32> %t3
1215 ; If the shuffle has no undefs, it's safe to shuffle the variables first.
1217 define <4 x i32> @urem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1218 ; CHECK-LABEL: @urem_2_vars(
1219 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1220 ; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 8>, [[TMP1]]
1221 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1223   %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1224   %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1225   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1226   ret <4 x i32> %t3
1229 define <4 x i32> @srem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1230 ; CHECK-LABEL: @srem_2_vars(
1231 ; CHECK-NEXT:    [[T1:%.*]] = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1232 ; CHECK-NEXT:    [[T2:%.*]] = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]
1233 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 poison, i32 6, i32 3>
1234 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1236   %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1237   %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1
1238   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 6, i32 3>
1239   ret <4 x i32> %t3
1242 ; Try FP ops/types.
1244 define <4 x float> @fadd_2_vars(<4 x float> %v0, <4 x float> %v1) {
1245 ; CHECK-LABEL: @fadd_2_vars(
1246 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1247 ; CHECK-NEXT:    [[T3:%.*]] = fadd <4 x float> [[TMP1]], <float 1.000000e+00, float 2.000000e+00, float 7.000000e+00, float 8.000000e+00>
1248 ; CHECK-NEXT:    ret <4 x float> [[T3]]
1250   %t1 = fadd <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>
1251   %t2 = fadd <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>
1252   %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1253   ret <4 x float> %t3
1256 define <4 x double> @fsub_2_vars(<4 x double> %v0, <4 x double> %v1) {
1257 ; CHECK-LABEL: @fsub_2_vars(
1258 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>
1259 ; CHECK-NEXT:    [[T3:%.*]] = fsub <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]
1260 ; CHECK-NEXT:    ret <4 x double> [[T3]]
1262   %t1 = fsub <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
1263   %t2 = fsub <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v1
1264   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
1265   ret <4 x double> %t3
1268 ; Intersect any FMF.
1270 define <4 x float> @fmul_2_vars(<4 x float> %v0, <4 x float> %v1) {
1271 ; CHECK-LABEL: @fmul_2_vars(
1272 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
1273 ; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc nsz <4 x float> [[TMP1]], <float 1.000000e+00, float 6.000000e+00, float 7.000000e+00, float 8.000000e+00>
1274 ; CHECK-NEXT:    ret <4 x float> [[T3]]
1276   %t1 = fmul reassoc nsz <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>
1277   %t2 = fmul reassoc nsz <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>
1278   %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
1279   ret <4 x float> %t3
1282 define <4 x double> @frem_2_vars(<4 x double> %v0, <4 x double> %v1) {
1283 ; CHECK-LABEL: @frem_2_vars(
1284 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>
1285 ; CHECK-NEXT:    [[T3:%.*]] = frem <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]
1286 ; CHECK-NEXT:    ret <4 x double> [[T3]]
1288   %t1 = frem nnan ninf <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
1289   %t2 = frem nnan arcp <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v1
1290   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>
1291   ret <4 x double> %t3
1294 ; The variable operand must be either the first operand or second operand in both binops.
1296 define <4 x double> @fdiv_2_vars(<4 x double> %v0, <4 x double> %v1) {
1297 ; CHECK-LABEL: @fdiv_2_vars(
1298 ; CHECK-NEXT:    [[T1:%.*]] = fdiv <4 x double> <double 1.000000e+00, double 2.000000e+00, double poison, double poison>, [[V0:%.*]]
1299 ; CHECK-NEXT:    [[T2:%.*]] = fdiv <4 x double> [[V1:%.*]], <double poison, double poison, double 7.000000e+00, double 8.000000e+00>
1300 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1301 ; CHECK-NEXT:    ret <4 x double> [[T3]]
1303   %t1 = fdiv <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0
1304   %t2 = fdiv <4 x double> %v1, <double 5.0, double 6.0, double 7.0, double 8.0>
1305   %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1306   ret <4 x double> %t3
1309 ; Shift-left with constant shift amount can be converted to mul to enable the fold.
1311 define <4 x i32> @mul_shl(<4 x i32> %v0) {
1312 ; CHECK-LABEL: @mul_shl(
1313 ; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[V0:%.*]], <i32 32, i32 64, i32 3, i32 4>
1314 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1316   %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1317   %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
1318   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1319   ret <4 x i32> %t3
1322 ; Try with shift as operand 0 of the shuffle; 'nsw' is dropped for safety, but that could be improved.
1324 define <4 x i32> @shl_mul(<4 x i32> %v0) {
1325 ; CHECK-LABEL: @shl_mul(
1326 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[V0:%.*]], <i32 5, i32 undef, i32 8, i32 16>
1327 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1329   %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1330   %t2 = mul nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
1331   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>
1332   ret <4 x i32> %t3
1335 ; Demanded elements + simplification can remove the mul alone, but that's not the best case.
1337 define <4 x i32> @mul_is_nop_shl(<4 x i32> %v0) {
1338 ; CHECK-LABEL: @mul_is_nop_shl(
1339 ; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 7, i32 8>
1340 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1342   %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1343   %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
1344   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
1345   ret <4 x i32> %t3
1348 ; Negative test: shift amount (operand 1) must be constant.
1350 define <4 x i32> @shl_mul_not_constant_shift_amount(<4 x i32> %v0) {
1351 ; CHECK-LABEL: @shl_mul_not_constant_shift_amount(
1352 ; CHECK-NEXT:    [[T1:%.*]] = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]
1353 ; CHECK-NEXT:    [[T2:%.*]] = mul <4 x i32> [[V0]], <i32 5, i32 6, i32 poison, i32 poison>
1354 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T2]], <4 x i32> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1355 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1357   %t1 = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0
1358   %t2 = mul <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>
1359   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1360   ret <4 x i32> %t3
1363 ; Try with 2 variable inputs.
1365 define <4 x i32> @mul_shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1366 ; CHECK-LABEL: @mul_shl_2_vars(
1367 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1368 ; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], <i32 32, i32 64, i32 3, i32 4>
1369 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1371   %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1372   %t2 = shl nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1373   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1374   ret <4 x i32> %t3
1377 define <4 x i32> @shl_mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
1378 ; CHECK-LABEL: @shl_mul_2_vars(
1379 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 poison, i32 6, i32 7>
1380 ; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 5, i32 undef, i32 8, i32 16>
1381 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1383   %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>
1384   %t2 = mul nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>
1385   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>
1386   ret <4 x i32> %t3
1389 ; Or with constant can be converted to add to enable the fold.
1390 ; The 'shl' is here to allow analysis to determine that the 'or' can be transformed to 'add'.
1391 ; TODO: The 'or' constant is limited to a splat.
1393 define <4 x i32> @add_or(<4 x i32> %v) {
1394 ; CHECK-LABEL: @add_or(
1395 ; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], <i32 5, i32 5, i32 5, i32 5>
1396 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0]], <i32 31, i32 31, i32 65536, i32 65537>
1397 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1399   %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits
1400   %t1 = add <4 x i32> %v0, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'
1401   %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits
1402   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1403   ret <4 x i32> %t3
1406 ; Try with 'or' as operand 0 of the shuffle.
1408 define <4 x i8> @or_add(<4 x i8> %v) {
1409 ; CHECK-LABEL: @or_add(
1410 ; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], <i8 3, i8 3, i8 3, i8 3>
1411 ; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 -64, i8 -64>
1412 ; CHECK-NEXT:    ret <4 x i8> [[T3]]
1414   %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits
1415   %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits
1416   %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'
1417   %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1418   ret <4 x i8> %t3
1421 ; Negative test: not all 'or' insts can be converted to 'add'.
1423 define <4 x i8> @or_add_not_enough_masking(<4 x i8> %v) {
1424 ; CHECK-LABEL: @or_add_not_enough_masking(
1425 ; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], <i8 1, i8 1, i8 1, i8 1>
1426 ; CHECK-NEXT:    [[T1:%.*]] = or <4 x i8> [[V0]], <i8 poison, i8 poison, i8 -64, i8 -64>
1427 ; CHECK-NEXT:    [[T2:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 poison, i8 poison>
1428 ; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i8> [[T2]], <4 x i8> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1429 ; CHECK-NEXT:    ret <4 x i8> [[T3]]
1431   %v0 = lshr <4 x i8> %v, <i8 1, i8 1, i8 1, i8 1>          ; clear not enough top bits
1432   %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits
1433   %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'
1434   %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1435   ret <4 x i8> %t3
1438 ; Try with 2 variable inputs.
1440 define <4 x i32> @add_or_2_vars(<4 x i32> %v, <4 x i32> %v1) {
1441 ; CHECK-LABEL: @add_or_2_vars(
1442 ; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], <i32 5, i32 5, i32 5, i32 5>
1443 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1444 ; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[TMP1]], <i32 31, i32 31, i32 65536, i32 65537>
1445 ; CHECK-NEXT:    ret <4 x i32> [[T3]]
1447   %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits
1448   %t1 = add <4 x i32> %v1, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'
1449   %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits
1450   %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1451   ret <4 x i32> %t3
1454 define <4 x i8> @or_add_2_vars(<4 x i8> %v, <4 x i8> %v1) {
1455 ; CHECK-LABEL: @or_add_2_vars(
1456 ; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], <i8 3, i8 3, i8 3, i8 3>
1457 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i8> [[V1:%.*]], <4 x i8> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
1458 ; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[TMP1]], <i8 1, i8 2, i8 -64, i8 -64>
1459 ; CHECK-NEXT:    ret <4 x i8> [[T3]]
1461   %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits
1462   %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits
1463   %t2 = add nsw nuw <4 x i8> %v1, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'
1464   %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
1465   ret <4 x i8> %t3
1468 ; The undef operand is used to simplify the shuffle mask, but don't assert that too soon.
1470 define <4 x i32> @PR41419(<4 x i32> %v) {
1471 ; CHECK-LABEL: @PR41419(
1472 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 poison, i32 2, i32 poison>
1473 ; CHECK-NEXT:    ret <4 x i32> [[S]]
1475   %s = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
1476   ret <4 x i32> %s