xref: /llvm-project/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4declare i1 @llvm.umin.i1(i1, i1)
5declare i8 @llvm.umin.i8(i8, i8)
6declare i8 @llvm.umax.i8(i8, i8)
7declare i8 @llvm.smin.i8(i8, i8)
8declare i8 @llvm.smax.i8(i8, i8)
9declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)
10declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)
11declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)
12declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)
13declare void @use(i8)
14declare void @use_vec(<3 x i8>)
15
16define i8 @umin_known_bits(i8 %x, i8 %y) {
17; CHECK-LABEL: @umin_known_bits(
18; CHECK-NEXT:    ret i8 0
19;
20  %x2 = and i8 %x, 127
21  %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y)
22  %r = and i8 %m, -128
23  ret i8 %r
24}
25
26define i8 @umax_known_bits(i8 %x, i8 %y) {
27; CHECK-LABEL: @umax_known_bits(
28; CHECK-NEXT:    ret i8 -128
29;
30  %x2 = or i8 %x, -128
31  %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y)
32  %r = and i8 %m, -128
33  ret i8 %r
34}
35
36define i8 @smin_known_bits(i8 %x, i8 %y) {
37; CHECK-LABEL: @smin_known_bits(
38; CHECK-NEXT:    ret i8 -128
39;
40  %x2 = or i8 %x, -128
41  %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y)
42  %r = and i8 %m, -128
43  ret i8 %r
44}
45
46define i8 @smax_known_bits(i8 %x, i8 %y) {
47; CHECK-LABEL: @smax_known_bits(
48; CHECK-NEXT:    ret i8 0
49;
50  %x2 = and i8 %x, 127
51  %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y)
52  %r = and i8 %m, -128
53  ret i8 %r
54}
55
56define i8 @smax_sext(i5 %x, i5 %y) {
57; CHECK-LABEL: @smax_sext(
58; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
59; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
60; CHECK-NEXT:    ret i8 [[M]]
61;
62  %sx = sext i5 %x to i8
63  %sy = sext i5 %y to i8
64  %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy)
65  ret i8 %m
66}
67
68; Extra use is ok.
69
70define i8 @smin_sext(i5 %x, i5 %y) {
71; CHECK-LABEL: @smin_sext(
72; CHECK-NEXT:    [[SY:%.*]] = sext i5 [[Y:%.*]] to i8
73; CHECK-NEXT:    call void @use(i8 [[SY]])
74; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Y]])
75; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
76; CHECK-NEXT:    ret i8 [[M]]
77;
78  %sx = sext i5 %x to i8
79  %sy = sext i5 %y to i8
80  call void @use(i8 %sy)
81  %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy)
82  ret i8 %m
83}
84
85; Sext doesn't change unsigned min/max comparison of narrow values.
86
87define i8 @umax_sext(i5 %x, i5 %y) {
88; CHECK-LABEL: @umax_sext(
89; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
90; CHECK-NEXT:    call void @use(i8 [[SX]])
91; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X]], i5 [[Y:%.*]])
92; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
93; CHECK-NEXT:    ret i8 [[M]]
94;
95  %sx = sext i5 %x to i8
96  call void @use(i8 %sx)
97  %sy = sext i5 %y to i8
98  %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy)
99  ret i8 %m
100}
101
102define <3 x i8> @umin_sext(<3 x i5> %x, <3 x i5> %y) {
103; CHECK-LABEL: @umin_sext(
104; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> [[Y:%.*]])
105; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
106; CHECK-NEXT:    ret <3 x i8> [[M]]
107;
108  %sx = sext <3 x i5> %x to <3 x i8>
109  %sy = sext <3 x i5> %y to <3 x i8>
110  %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
111  ret <3 x i8> %m
112}
113
114; Negative test - zext may change sign of inputs
115
116define i8 @smax_zext(i5 %x, i5 %y) {
117; CHECK-LABEL: @smax_zext(
118; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
119; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
120; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]])
121; CHECK-NEXT:    ret i8 [[M]]
122;
123  %zx = zext i5 %x to i8
124  %zy = zext i5 %y to i8
125  %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy)
126  ret i8 %m
127}
128
129; Negative test - zext may change sign of inputs
130
131define i8 @smin_zext(i5 %x, i5 %y) {
132; CHECK-LABEL: @smin_zext(
133; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
134; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
135; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]])
136; CHECK-NEXT:    ret i8 [[M]]
137;
138  %zx = zext i5 %x to i8
139  %zy = zext i5 %y to i8
140  %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy)
141  ret i8 %m
142}
143
144define i8 @umax_zext(i5 %x, i5 %y) {
145; CHECK-LABEL: @umax_zext(
146; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
147; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
148; CHECK-NEXT:    ret i8 [[M]]
149;
150  %zx = zext i5 %x to i8
151  %zy = zext i5 %y to i8
152  %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy)
153  ret i8 %m
154}
155
156define i8 @umin_zext(i5 %x, i5 %y) {
157; CHECK-LABEL: @umin_zext(
158; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
159; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
160; CHECK-NEXT:    ret i8 [[M]]
161;
162  %zx = zext i5 %x to i8
163  %zy = zext i5 %y to i8
164  %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
165  ret i8 %m
166}
167
168; Negative test - mismatched types
169
170define i8 @umin_zext_types(i6 %x, i5 %y) {
171; CHECK-LABEL: @umin_zext_types(
172; CHECK-NEXT:    [[ZX:%.*]] = zext i6 [[X:%.*]] to i8
173; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
174; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
175; CHECK-NEXT:    ret i8 [[M]]
176;
177  %zx = zext i6 %x to i8
178  %zy = zext i5 %y to i8
179  %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
180  ret i8 %m
181}
182
183; Negative test - mismatched extends
184
185define i8 @umin_ext(i5 %x, i5 %y) {
186; CHECK-LABEL: @umin_ext(
187; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
188; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
189; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]])
190; CHECK-NEXT:    ret i8 [[M]]
191;
192  %sx = sext i5 %x to i8
193  %zy = zext i5 %y to i8
194  %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy)
195  ret i8 %m
196}
197
198; Negative test - too many uses.
199
200define i8 @umin_zext_uses(i5 %x, i5 %y) {
201; CHECK-LABEL: @umin_zext_uses(
202; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
203; CHECK-NEXT:    call void @use(i8 [[ZX]])
204; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
205; CHECK-NEXT:    call void @use(i8 [[ZY]])
206; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
207; CHECK-NEXT:    ret i8 [[M]]
208;
209  %zx = zext i5 %x to i8
210  call void @use(i8 %zx)
211  %zy = zext i5 %y to i8
212  call void @use(i8 %zy)
213  %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
214  ret i8 %m
215}
216
217define i8 @smax_sext_constant(i5 %x) {
218; CHECK-LABEL: @smax_sext_constant(
219; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
220; CHECK-NEXT:    [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
221; CHECK-NEXT:    ret i8 [[M]]
222;
223  %e = sext i5 %x to i8
224  %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
225  ret i8 %m
226}
227
228; simplifies
229
230define i8 @smax_sext_constant_big(i5 %x) {
231; CHECK-LABEL: @smax_sext_constant_big(
232; CHECK-NEXT:    ret i8 16
233;
234  %e = sext i5 %x to i8
235  %m = call i8 @llvm.smax.i8(i8 %e, i8 16)
236  ret i8 %m
237}
238
239; negative test
240
241define i8 @smax_zext_constant(i5 %x) {
242; CHECK-LABEL: @smax_zext_constant(
243; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
244; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
245; CHECK-NEXT:    ret i8 [[M]]
246;
247  %e = zext i5 %x to i8
248  %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
249  ret i8 %m
250}
251
252define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
253; CHECK-LABEL: @smin_sext_constant(
254; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
255; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
256; CHECK-NEXT:    ret <3 x i8> [[M]]
257;
258  %e = sext <3 x i5> %x to <3 x i8>
259  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>)
260  ret <3 x i8> %m
261}
262
263; negative test
264
265define i8 @smin_zext_constant(i5 %x) {
266; CHECK-LABEL: @smin_zext_constant(
267; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
268; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7)
269; CHECK-NEXT:    ret i8 [[M]]
270;
271  %e = zext i5 %x to i8
272  %m = call i8 @llvm.smin.i8(i8 %e, i8 7)
273  ret i8 %m
274}
275
276define i8 @umax_sext_constant(i5 %x) {
277; CHECK-LABEL: @umax_sext_constant(
278; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
279; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
280; CHECK-NEXT:    ret i8 [[M]]
281;
282  %e = sext i5 %x to i8
283  %m = call i8 @llvm.umax.i8(i8 %e, i8 7)
284  ret i8 %m
285}
286
287; negative test
288
289define i8 @umax_sext_constant_big(i5 %x) {
290; CHECK-LABEL: @umax_sext_constant_big(
291; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
292; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126)
293; CHECK-NEXT:    ret i8 [[M]]
294;
295  %e = sext i5 %x to i8
296  %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
297  ret i8 %m
298}
299
300define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
301; CHECK-LABEL: @umax_zext_constant(
302; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
303; CHECK-NEXT:    [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
304; CHECK-NEXT:    ret <3 x i8> [[M]]
305;
306  %e = zext <3 x i5> %x to <3 x i8>
307  %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>)
308  ret <3 x i8> %m
309}
310
311; simplifies
312
313define i8 @umax_zext_constant_big(i5 %x) {
314; CHECK-LABEL: @umax_zext_constant_big(
315; CHECK-NEXT:    ret i8 126
316;
317  %e = zext i5 %x to i8
318  %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
319  ret i8 %m
320}
321
322define i8 @umin_sext_constant(i5 %x) {
323; CHECK-LABEL: @umin_sext_constant(
324; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
325; CHECK-NEXT:    [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
326; CHECK-NEXT:    ret i8 [[M]]
327;
328  %e = sext i5 %x to i8
329  %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
330  ret i8 %m
331}
332
333; negative test
334
335define i8 @umin_sext_constant_big(i5 %x) {
336; CHECK-LABEL: @umin_sext_constant_big(
337; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
338; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126)
339; CHECK-NEXT:    ret i8 [[M]]
340;
341  %e = sext i5 %x to i8
342  %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
343  ret i8 %m
344}
345
346define i8 @umin_zext_constant(i5 %x) {
347; CHECK-LABEL: @umin_zext_constant(
348; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
349; CHECK-NEXT:    [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
350; CHECK-NEXT:    ret i8 [[M]]
351;
352  %e = zext i5 %x to i8
353  %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
354  ret i8 %m
355}
356
357; simplifies
358
359define i8 @umin_zext_constant_big(i5 %x) {
360; CHECK-LABEL: @umin_zext_constant_big(
361; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
362; CHECK-NEXT:    ret i8 [[E]]
363;
364  %e = zext i5 %x to i8
365  %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
366  ret i8 %m
367}
368
369; negative test
370
371define i8 @umin_zext_constant_uses(i5 %x) {
372; CHECK-LABEL: @umin_zext_constant_uses(
373; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
374; CHECK-NEXT:    call void @use(i8 [[E]])
375; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
376; CHECK-NEXT:    ret i8 [[M]]
377;
378  %e = zext i5 %x to i8
379  call void @use(i8 %e)
380  %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
381  ret i8 %m
382}
383
384define i8 @smax_of_nots(i8 %x, i8 %y) {
385; CHECK-LABEL: @smax_of_nots(
386; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
387; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
388; CHECK-NEXT:    ret i8 [[M]]
389;
390  %notx = xor i8 %x, -1
391  %noty = xor i8 %y, -1
392  %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
393  ret i8 %m
394}
395
396; Vectors are ok (including poison lanes of not ops)
397
398define <3 x i8> @smin_of_nots(<3 x i8> %x, <3 x i8> %y) {
399; CHECK-LABEL: @smin_of_nots(
400; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
401; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1)
402; CHECK-NEXT:    ret <3 x i8> [[M]]
403;
404  %notx = xor <3 x i8> %x, <i8 -1, i8 poison, i8 -1>
405  %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 poison>
406  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty)
407  ret <3 x i8> %m
408}
409
410; An extra use is ok.
411
412define i8 @umax_of_nots(i8 %x, i8 %y) {
413; CHECK-LABEL: @umax_of_nots(
414; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
415; CHECK-NEXT:    call void @use(i8 [[NOTX]])
416; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]])
417; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
418; CHECK-NEXT:    ret i8 [[M]]
419;
420  %notx = xor i8 %x, -1
421  call void @use(i8 %notx)
422  %noty = xor i8 %y, -1
423  %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty)
424  ret i8 %m
425}
426
427; An extra use is ok.
428
429define i8 @umin_of_nots(i8 %x, i8 %y) {
430; CHECK-LABEL: @umin_of_nots(
431; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
432; CHECK-NEXT:    call void @use(i8 [[NOTY]])
433; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y]])
434; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
435; CHECK-NEXT:    ret i8 [[M]]
436;
437  %notx = xor i8 %x, -1
438  %noty = xor i8 %y, -1
439  call void @use(i8 %noty)
440  %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
441  ret i8 %m
442}
443
444; Negative test - too many uses
445
446define i8 @umin_of_nots_uses(i8 %x, i8 %y) {
447; CHECK-LABEL: @umin_of_nots_uses(
448; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
449; CHECK-NEXT:    call void @use(i8 [[NOTX]])
450; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
451; CHECK-NEXT:    call void @use(i8 [[NOTY]])
452; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[NOTY]])
453; CHECK-NEXT:    ret i8 [[M]]
454;
455  %notx = xor i8 %x, -1
456  call void @use(i8 %notx)
457  %noty = xor i8 %y, -1
458  call void @use(i8 %noty)
459  %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
460  ret i8 %m
461}
462
463; Canonicalize 'not' after min/max.
464
465define i8 @smax_of_not_and_const(i8 %x) {
466; CHECK-LABEL: @smax_of_not_and_const(
467; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -43)
468; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
469; CHECK-NEXT:    ret i8 [[M]]
470;
471  %notx = xor i8 %x, -1
472  %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)
473  ret i8 %m
474}
475
476; Vectors are ok (including poison lanes of not ops and min/max constant operand)
477
478define <3 x i8> @smin_of_not_and_const(<3 x i8> %x) {
479; CHECK-LABEL: @smin_of_not_and_const(
480; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -43, i8 poison, i8 -44>)
481; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1)
482; CHECK-NEXT:    ret <3 x i8> [[M]]
483;
484  %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 poison>
485  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 poison, i8 43>, <3 x i8> %notx)
486  ret <3 x i8> %m
487}
488
489define i8 @umax_of_not_and_const(i8 %x) {
490; CHECK-LABEL: @umax_of_not_and_const(
491; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -45)
492; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
493; CHECK-NEXT:    ret i8 [[M]]
494;
495  %notx = xor i8 %x, -1
496  %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)
497  ret i8 %m
498}
499
500define i8 @umin_of_not_and_const(i8 %x) {
501; CHECK-LABEL: @umin_of_not_and_const(
502; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 44)
503; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
504; CHECK-NEXT:    ret i8 [[M]]
505;
506  %notx = xor i8 %x, -1
507  %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
508  ret i8 %m
509}
510
511define i8 @umin_of_not_and_smax(i8 %x, i8 %y, i8 %z) {
512; CHECK-LABEL: @umin_of_not_and_smax(
513; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
514; CHECK-NEXT:    call void @use(i8 [[NOTY]])
515; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
516; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
517; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[Z]])
518; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[TMP1]])
519; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
520; CHECK-NEXT:    ret i8 [[M2]]
521;
522  %notx = xor i8 %x, -1
523  %noty = xor i8 %y, -1
524  call void @use(i8 %noty)
525  %notz = xor i8 %z, -1
526  call void @use(i8 %notz)
527  %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz)
528  %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx)
529  ret i8 %m2
530}
531
532define i8 @smin_of_umax_and_not(i8 %x, i8 %y, i8 %z) {
533; CHECK-LABEL: @smin_of_umax_and_not(
534; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
535; CHECK-NEXT:    call void @use(i8 [[NOTY]])
536; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
537; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
538; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
539; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[TMP1]])
540; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
541; CHECK-NEXT:    ret i8 [[M2]]
542;
543  %notx = xor i8 %x, -1
544  %noty = xor i8 %y, -1
545  call void @use(i8 %noty)
546  %notz = xor i8 %z, -1
547  call void @use(i8 %notz)
548  %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz)
549  %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1)
550  ret i8 %m2
551}
552
553; Negative test - don't infinite loop on constant expression
554
555define i8 @umin_of_not_and_nontrivial_const(i8 %x) {
556; CHECK-LABEL: @umin_of_not_and_nontrivial_const(
557; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
558; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8))
559; CHECK-NEXT:    ret i8 [[M]]
560;
561  %notx = xor i8 %x, -1
562  %m = call i8 @llvm.umin.i8(i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8), i8 %notx)
563  ret i8 %m
564}
565
566; Negative test - too many uses
567
568define i8 @umin_of_not_and_const_uses(i8 %x) {
569; CHECK-LABEL: @umin_of_not_and_const_uses(
570; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
571; CHECK-NEXT:    call void @use(i8 [[NOTX]])
572; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45)
573; CHECK-NEXT:    ret i8 [[M]]
574;
575  %notx = xor i8 %x, -1
576  call void @use(i8 %notx)
577  %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
578  ret i8 %m
579}
580
581define i8 @not_smax_of_nots(i8 %x, i8 %y) {
582; CHECK-LABEL: @not_smax_of_nots(
583; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
584; CHECK-NEXT:    call void @use(i8 [[NOTX]])
585; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
586; CHECK-NEXT:    call void @use(i8 [[NOTY]])
587; CHECK-NEXT:    [[NOTM:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
588; CHECK-NEXT:    ret i8 [[NOTM]]
589;
590  %notx = xor i8 %x, -1
591  call void @use(i8 %notx)
592  %noty = xor i8 %y, -1
593  call void @use(i8 %noty)
594  %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
595  %notm = xor i8 %m, -1
596  ret i8 %notm
597}
598
599define i8 @not_smin_of_nots(i8 %x, i8 %y) {
600; CHECK-LABEL: @not_smin_of_nots(
601; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
602; CHECK-NEXT:    call void @use(i8 [[NOTX]])
603; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
604; CHECK-NEXT:    call void @use(i8 [[NOTY]])
605; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]])
606; CHECK-NEXT:    call void @use(i8 [[M]])
607; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
608; CHECK-NEXT:    ret i8 [[NOTM]]
609;
610  %notx = xor i8 %x, -1
611  call void @use(i8 %notx)
612  %noty = xor i8 %y, -1
613  call void @use(i8 %noty)
614  %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty)
615  call void @use(i8 %m)
616  %notm = xor i8 %m, -1
617  ret i8 %notm
618}
619
620define i8 @not_umax_of_not(i8 %x, i8 %y) {
621; CHECK-LABEL: @not_umax_of_not(
622; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
623; CHECK-NEXT:    call void @use(i8 [[NOTX]])
624; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
625; CHECK-NEXT:    [[NOTM:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])
626; CHECK-NEXT:    ret i8 [[NOTM]]
627;
628  %notx = xor i8 %x, -1
629  call void @use(i8 %notx)
630  %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)
631  %notm = xor i8 %m, -1
632  ret i8 %notm
633}
634
635; Negative test - this would require an extra instruction.
636
637define i8 @not_umin_of_not(i8 %x, i8 %y) {
638; CHECK-LABEL: @not_umin_of_not(
639; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
640; CHECK-NEXT:    call void @use(i8 [[NOTX]])
641; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]])
642; CHECK-NEXT:    call void @use(i8 [[M]])
643; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
644; CHECK-NEXT:    ret i8 [[NOTM]]
645;
646  %notx = xor i8 %x, -1
647  call void @use(i8 %notx)
648  %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y)
649  call void @use(i8 %m)
650  %notm = xor i8 %m, -1
651  ret i8 %notm
652}
653
654define i8 @not_umin_of_not_constant_op(i8 %x) {
655; CHECK-LABEL: @not_umin_of_not_constant_op(
656; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
657; CHECK-NEXT:    call void @use(i8 [[NOTX]])
658; CHECK-NEXT:    [[NOTM:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43)
659; CHECK-NEXT:    ret i8 [[NOTM]]
660;
661  %notx = xor i8 %x, -1
662  call void @use(i8 %notx)
663  %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)
664  %notm = xor i8 %m, -1
665  ret i8 %notm
666}
667
668define i8 @smax_negation(i8 %x, i8 %y) {
669; CHECK-LABEL: @smax_negation(
670; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
671; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
672; CHECK-NEXT:    ret i8 [[R]]
673;
674  %s1 = sub i8 %x, %y
675  %s2 = sub i8 %y, %x
676  %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
677  ret i8 %r
678}
679
680define i8 @smax_negation_nsw(i8 %x, i8 %y) {
681; CHECK-LABEL: @smax_negation_nsw(
682; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
683; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
684; CHECK-NEXT:    ret i8 [[R]]
685;
686  %s1 = sub nsw i8 %x, %y
687  %s2 = sub nsw i8 %y, %x
688  %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
689  ret i8 %r
690}
691
692define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
693; CHECK-LABEL: @smax_negation_not_nsw(
694; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
695; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
696; CHECK-NEXT:    ret i8 [[R]]
697;
698  %s1 = sub nsw i8 %x, %y
699  %s2 = sub nuw i8 %y, %x
700  %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
701  ret i8 %r
702}
703
704define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
705; CHECK-LABEL: @smax_negation_vec(
706; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
707; CHECK-NEXT:    ret <3 x i8> [[R]]
708;
709  %s = sub <3 x i8> <i8 0, i8 poison, i8 0>, %x
710  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
711  ret <3 x i8> %r
712}
713
714define i8 @smin_negation(i8 %x, i8 %y) {
715; CHECK-LABEL: @smin_negation(
716; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
717; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
718; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
719; CHECK-NEXT:    ret i8 [[NABS]]
720;
721  %s1 = sub i8 %x, %y
722  %s2 = sub i8 %y, %x
723  %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)
724  ret i8 %r
725}
726
727define i8 @umax_negation(i8 %x, i8 %y) {
728; CHECK-LABEL: @umax_negation(
729; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
730; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
731; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
732; CHECK-NEXT:    ret i8 [[NABS]]
733;
734  %s1 = sub nsw i8 %x, %y
735  %s2 = sub nsw i8 %y, %x
736  %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)
737  ret i8 %r
738}
739
740define i8 @umin_negation(i8 %x) {
741; CHECK-LABEL: @umin_negation(
742; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
743; CHECK-NEXT:    ret i8 [[R]]
744;
745  %s = sub nsw i8 0, %x
746  %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
747  ret i8 %r
748}
749
750define i8 @smax_negation_uses(i8 %x, i8 %y) {
751; CHECK-LABEL: @smax_negation_uses(
752; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
753; CHECK-NEXT:    call void @use(i8 [[S2]])
754; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false)
755; CHECK-NEXT:    ret i8 [[R]]
756;
757  %s1 = sub i8 %x, %y
758  %s2 = sub i8 %y, %x
759  call void @use(i8 %s2)
760  %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
761  ret i8 %r
762}
763
764define i8 @clamp_two_vals_smax_smin(i8 %x) {
765; CHECK-LABEL: @clamp_two_vals_smax_smin(
766; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43
767; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
768; CHECK-NEXT:    ret i8 [[R]]
769;
770  %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
771  %r = call i8 @llvm.smin.i8(i8 %m, i8 43)
772  ret i8 %r
773}
774
775define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) {
776; CHECK-LABEL: @clamp_two_vals_smin_smax(
777; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], splat (i8 41)
778; CHECK-NEXT:    [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> splat (i8 42), <3 x i8> splat (i8 41)
779; CHECK-NEXT:    ret <3 x i8> [[R]]
780;
781  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)
782  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)
783  ret <3 x i8> %r
784}
785
786define i8 @clamp_two_vals_umax_umin(i8 %x) {
787; CHECK-LABEL: @clamp_two_vals_umax_umin(
788; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43
789; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
790; CHECK-NEXT:    ret i8 [[R]]
791;
792  %m = call i8 @llvm.umax.i8(i8 %x, i8 42)
793  %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
794  ret i8 %r
795}
796
797define i8 @clamp_two_vals_umin_umax(i8 %x) {
798; CHECK-LABEL: @clamp_two_vals_umin_umax(
799; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41
800; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41
801; CHECK-NEXT:    ret i8 [[R]]
802;
803  %m = call i8 @llvm.umin.i8(i8 %x, i8 42)
804  %r = call i8 @llvm.umax.i8(i8 %m, i8 41)
805  ret i8 %r
806}
807
808; Negative test - mismatched signs
809
810define i8 @clamp_two_vals_smax_umin(i8 %x) {
811; CHECK-LABEL: @clamp_two_vals_smax_umin(
812; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
813; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43)
814; CHECK-NEXT:    ret i8 [[R]]
815;
816  %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
817  %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
818  ret i8 %r
819}
820
821; Negative test - wrong range
822
823define i8 @clamp_three_vals_smax_smin(i8 %x) {
824; CHECK-LABEL: @clamp_three_vals_smax_smin(
825; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
826; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44)
827; CHECK-NEXT:    ret i8 [[R]]
828;
829  %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
830  %r = call i8 @llvm.smin.i8(i8 %m, i8 44)
831  ret i8 %r
832}
833
834; Edge cases are simplified
835
836define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
837; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
838; CHECK-NEXT:    ret i8 0
839;
840  %m = call i8 @llvm.umax.i8(i8 %x, i8 255)
841  %r = call i8 @llvm.umin.i8(i8 %m, i8 0)
842  ret i8 %r
843}
844
845; Edge cases are simplified
846
847define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
848; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
849; CHECK-NEXT:    ret i8 -1
850;
851  %m = call i8 @llvm.umin.i8(i8 %x, i8 0)
852  %r = call i8 @llvm.umax.i8(i8 %m, i8 255)
853  ret i8 %r
854}
855
856; Edge cases are simplified
857
858define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
859; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
860; CHECK-NEXT:    ret i8 -128
861;
862  %m = call i8 @llvm.smax.i8(i8 %x, i8 127)
863  %r = call i8 @llvm.smin.i8(i8 %m, i8 128)
864  ret i8 %r
865}
866
867; Edge cases are simplified
868
869define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
870; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
871; CHECK-NEXT:    ret i8 127
872;
873  %m = call i8 @llvm.smin.i8(i8 %x, i8 128)
874  %r = call i8 @llvm.smax.i8(i8 %m, i8 127)
875  ret i8 %r
876}
877
878
879define i8 @umin_non_zero_idiom1(i8 %a) {
880; CHECK-LABEL: @umin_non_zero_idiom1(
881; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
882; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
883; CHECK-NEXT:    ret i8 [[RES]]
884;
885  %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
886  ret i8 %res
887}
888
889define i8 @umin_non_zero_idiom2(i8 %a) {
890; CHECK-LABEL: @umin_non_zero_idiom2(
891; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
892; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
893; CHECK-NEXT:    ret i8 [[RES]]
894;
895  %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
896  ret i8 %res
897}
898
899define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
900; CHECK-LABEL: @umin_non_zero_idiom3(
901; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
902; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
903; CHECK-NEXT:    ret <3 x i8> [[RES]]
904;
905  %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
906  ret <3 x i8> %res
907}
908
909define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
910; CHECK-LABEL: @umin_non_zero_idiom4(
911; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
912; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
913; CHECK-NEXT:    ret <3 x i8> [[RES]]
914;
915  %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 poison, i8 poison>)
916  ret <3 x i8> %res
917}
918
919define i1 @umin_eq_zero(i8 %a, i8 %b) {
920; CHECK-LABEL: @umin_eq_zero(
921; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
922; CHECK-NEXT:    [[RES:%.*]] = icmp eq i8 [[UMIN]], 0
923; CHECK-NEXT:    ret i1 [[RES]]
924;
925  %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
926  %res = icmp eq i8 %umin, 0
927  ret i1 %res
928}
929
930define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) {
931; CHECK-LABEL: @umin_eq_zero2(
932; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
933; CHECK-NEXT:    [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer
934; CHECK-NEXT:    ret <3 x i1> [[RES]]
935;
936
937  %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
938  %res = icmp eq <3 x i8> %umin, zeroinitializer
939  ret <3 x i1> %res
940}
941
942define i1 @umin_ne_zero(i8 %a, i8 %b) {
943; CHECK-LABEL: @umin_ne_zero(
944; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
945; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8 [[UMIN]], 0
946; CHECK-NEXT:    ret i1 [[RES]]
947;
948  %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
949  %res = icmp ne i8 %umin, 0
950  ret i1 %res
951}
952
953define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) {
954; CHECK-LABEL: @umin_ne_zero2(
955; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
956; CHECK-NEXT:    [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer
957; CHECK-NEXT:    ret <3 x i1> [[RES]]
958;
959
960  %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
961  %res = icmp ne <3 x i8> %umin, zeroinitializer
962  ret <3 x i1> %res
963}
964
965define i8 @smax(i8 %x, i8 %y, i8 %z) {
966; CHECK-LABEL: @smax(
967; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]])
968; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]])
969; CHECK-NEXT:    ret i8 [[M3]]
970;
971  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
972  %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
973  %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
974  ret i8 %m3
975}
976
977define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
978; CHECK-LABEL: @smin(
979; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]])
980; CHECK-NEXT:    [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]])
981; CHECK-NEXT:    ret <3 x i8> [[M3]]
982;
983  %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)
984  %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)
985  %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)
986  ret <3 x i8> %m3
987}
988
989define i8 @umax(i8 %x, i8 %y, i8 %z) {
990; CHECK-LABEL: @umax(
991; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
992; CHECK-NEXT:    call void @use(i8 [[M1]])
993; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]])
994; CHECK-NEXT:    ret i8 [[M3]]
995;
996  %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
997  call void @use(i8 %m1)
998  %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)
999  %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)
1000  ret i8 %m3
1001}
1002
1003define i8 @umin(i8 %x, i8 %y, i8 %z) {
1004; CHECK-LABEL: @umin(
1005; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]])
1006; CHECK-NEXT:    call void @use(i8 [[M2]])
1007; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]])
1008; CHECK-NEXT:    ret i8 [[M3]]
1009;
1010  %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
1011  %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)
1012  call void @use(i8 %m2)
1013  %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)
1014  ret i8 %m3
1015}
1016
1017; negative test - too many uses
1018
1019define i8 @smax_uses(i8 %x, i8 %y, i8 %z) {
1020; CHECK-LABEL: @smax_uses(
1021; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1022; CHECK-NEXT:    call void @use(i8 [[M1]])
1023; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]])
1024; CHECK-NEXT:    call void @use(i8 [[M2]])
1025; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1026; CHECK-NEXT:    ret i8 [[M3]]
1027;
1028  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1029  call void @use(i8 %m1)
1030  %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
1031  call void @use(i8 %m2)
1032  %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1033  ret i8 %m3
1034}
1035
1036; negative test - must have common operand
1037
1038define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) {
1039; CHECK-LABEL: @smax_no_common_op(
1040; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1041; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]])
1042; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1043; CHECK-NEXT:    ret i8 [[M3]]
1044;
1045  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1046  %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)
1047  %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1048  ret i8 %m3
1049}
1050
1051define i8 @umax_demand_lshr(i8 %x) {
1052; CHECK-LABEL: @umax_demand_lshr(
1053; CHECK-NEXT:    [[R:%.*]] = lshr i8 [[X:%.*]], 4
1054; CHECK-NEXT:    ret i8 [[R]]
1055;
1056  %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1057  %r = lshr i8 %m, 4
1058  ret i8 %r
1059}
1060
1061define i8 @umax_demand_and(i8 %x) {
1062; CHECK-LABEL: @umax_demand_and(
1063; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], 10
1064; CHECK-NEXT:    ret i8 [[R]]
1065;
1066  %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1067  %r = and i8 %m, 10
1068  ret i8 %r
1069}
1070
1071define i8 @umin_demand_or_31_30(i8 %x) {
1072; CHECK-LABEL: @umin_demand_or_31_30(
1073; CHECK-NEXT:    [[R:%.*]] = or i8 [[X:%.*]], 31
1074; CHECK-NEXT:    ret i8 [[R]]
1075;
1076  %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1077  %r = or i8 %m, 31
1078  ret i8 %r
1079}
1080
1081define i8 @umin_demand_and_7_8(i8 %x) {
1082; CHECK-LABEL: @umin_demand_and_7_8(
1083; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], -8
1084; CHECK-NEXT:    ret i8 [[R]]
1085;
1086  %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1087  %r = and i8 %m, -8
1088  ret i8 %r
1089}
1090
1091define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) {
1092; CHECK-LABEL: @neg_neg_nsw_smax(
1093; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1094; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1095; CHECK-NEXT:    ret i8 [[M]]
1096;
1097  %nx = sub nsw i8 0, %x
1098  %ny = sub nsw i8 0, %y
1099  %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1100  ret i8 %m
1101}
1102
1103define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) {
1104; CHECK-LABEL: @neg_neg_nsw_smin(
1105; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
1106; CHECK-NEXT:    [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]]
1107; CHECK-NEXT:    ret <3 x i8> [[M]]
1108;
1109  %nx = sub nsw <3 x i8> zeroinitializer, %x
1110  %ny = sub nsw <3 x i8> zeroinitializer, %y
1111  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)
1112  ret <3 x i8> %m
1113}
1114
1115define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) {
1116; CHECK-LABEL: @neg_neg_nsw_smax_use0(
1117; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1118; CHECK-NEXT:    call void @use(i8 [[NX]])
1119; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]])
1120; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1121; CHECK-NEXT:    ret i8 [[M]]
1122;
1123  %nx = sub nsw i8 0, %x
1124  call void @use(i8 %nx)
1125  %ny = sub nsw i8 0, %y
1126  %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1127  ret i8 %m
1128}
1129
1130define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) {
1131; CHECK-LABEL: @neg_neg_nsw_smin_use1(
1132; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1133; CHECK-NEXT:    call void @use(i8 [[NY]])
1134; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]])
1135; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1136; CHECK-NEXT:    ret i8 [[M]]
1137;
1138  %nx = sub nsw i8 0, %x
1139  %ny = sub nsw i8 0, %y
1140  call void @use(i8 %ny)
1141  %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1142  ret i8 %m
1143}
1144
1145; negative test - too many uses
1146
1147define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) {
1148; CHECK-LABEL: @neg_neg_nsw_smin_use2(
1149; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1150; CHECK-NEXT:    call void @use(i8 [[NX]])
1151; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1152; CHECK-NEXT:    call void @use(i8 [[NY]])
1153; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1154; CHECK-NEXT:    ret i8 [[M]]
1155;
1156  %nx = sub nsw i8 0, %x
1157  call void @use(i8 %nx)
1158  %ny = sub nsw i8 0, %y
1159  call void @use(i8 %ny)
1160  %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1161  ret i8 %m
1162}
1163
1164; negative test - need nsw on both ops
1165
1166define i8 @neg_neg_smax(i8 %x, i8 %y) {
1167; CHECK-LABEL: @neg_neg_smax(
1168; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1169; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1170; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]])
1171; CHECK-NEXT:    ret i8 [[M]]
1172;
1173  %nx = sub i8 0, %x
1174  %ny = sub nsw i8 0, %y
1175  %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1176  ret i8 %m
1177}
1178
1179; negative test - need nsw on both ops
1180
1181define i8 @neg_neg_smin(i8 %x, i8 %y) {
1182; CHECK-LABEL: @neg_neg_smin(
1183; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1184; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1185; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1186; CHECK-NEXT:    ret i8 [[M]]
1187;
1188  %nx = sub i8 0, %x
1189  %ny = sub nsw i8 0, %y
1190  %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1191  ret i8 %m
1192}
1193
1194; negative test - need signed min/max
1195
1196define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) {
1197; CHECK-LABEL: @neg_neg_nsw_umin(
1198; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1199; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1200; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
1201; CHECK-NEXT:    ret i8 [[M]]
1202;
1203  %nx = sub nsw i8 0, %x
1204  %ny = sub nsw i8 0, %y
1205  %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
1206  ret i8 %m
1207}
1208
1209define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {
1210; CHECK-LABEL: @freeToInvertSub(
1211; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1212; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1213; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1214; CHECK-NEXT:    call void @use(i8 [[NX]])
1215; CHECK-NEXT:    call void @use(i8 [[NY]])
1216; CHECK-NEXT:    call void @use(i8 [[NZ]])
1217; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1218; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[TMP1]], [[Z]]
1219; CHECK-NEXT:    ret i8 [[SUB]]
1220;
1221  %nx = xor i8 %x, -1
1222  %ny = xor i8 %y, -1
1223  %nz = xor i8 %z, -1
1224  call void @use(i8 %nx)
1225  call void @use(i8 %ny)
1226  call void @use(i8 %nz)
1227  %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1228  %sub = sub i8 %nz, %m
1229  ret i8 %sub
1230}
1231
1232define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {
1233; CHECK-LABEL: @freeToInvertSub_uses(
1234; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1235; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1236; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1237; CHECK-NEXT:    call void @use(i8 [[NX]])
1238; CHECK-NEXT:    call void @use(i8 [[NY]])
1239; CHECK-NEXT:    call void @use(i8 [[NZ]])
1240; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1241; CHECK-NEXT:    call void @use(i8 [[M]])
1242; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1243; CHECK-NEXT:    ret i8 [[SUB]]
1244;
1245  %nx = xor i8 %x, -1
1246  %ny = xor i8 %y, -1
1247  %nz = xor i8 %z, -1
1248  call void @use(i8 %nx)
1249  call void @use(i8 %ny)
1250  call void @use(i8 %nz)
1251  %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1252  call void @use(i8 %m)
1253  %sub = sub i8 %nz, %m
1254  ret i8 %sub
1255}
1256
1257define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {
1258; CHECK-LABEL: @freeToInvert(
1259; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1260; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1261; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1262; CHECK-NEXT:    call void @use(i8 [[NX]])
1263; CHECK-NEXT:    call void @use(i8 [[NY]])
1264; CHECK-NEXT:    call void @use(i8 [[NZ]])
1265; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1266; CHECK-NEXT:    [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1267; CHECK-NEXT:    ret i8 [[NOT]]
1268;
1269  %nx = xor i8 %x, -1
1270  %ny = xor i8 %y, -1
1271  %nz = xor i8 %z, -1
1272  call void @use(i8 %nx)
1273  call void @use(i8 %ny)
1274  call void @use(i8 %nz)
1275  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1276  %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1277  %not = xor i8 %m2, -1
1278  ret i8 %not
1279}
1280
1281define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {
1282; CHECK-LABEL: @freeToInvert_use1(
1283; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1284; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1285; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1286; CHECK-NEXT:    call void @use(i8 [[NX]])
1287; CHECK-NEXT:    call void @use(i8 [[NY]])
1288; CHECK-NEXT:    call void @use(i8 [[NZ]])
1289; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1290; CHECK-NEXT:    call void @use(i8 [[M1]])
1291; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[M1]], -1
1292; CHECK-NEXT:    [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1293; CHECK-NEXT:    ret i8 [[NOT]]
1294;
1295  %nx = xor i8 %x, -1
1296  %ny = xor i8 %y, -1
1297  %nz = xor i8 %z, -1
1298  call void @use(i8 %nx)
1299  call void @use(i8 %ny)
1300  call void @use(i8 %nz)
1301  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1302  call void @use(i8 %m1)
1303  %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1304  %not = xor i8 %m2, -1
1305  ret i8 %not
1306}
1307
1308define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {
1309; CHECK-LABEL: @freeToInvert_use2(
1310; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1311; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1312; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1313; CHECK-NEXT:    call void @use(i8 [[NX]])
1314; CHECK-NEXT:    call void @use(i8 [[NY]])
1315; CHECK-NEXT:    call void @use(i8 [[NZ]])
1316; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1317; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1318; CHECK-NEXT:    call void @use(i8 [[M2]])
1319; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1320; CHECK-NEXT:    ret i8 [[NOT]]
1321;
1322  %nx = xor i8 %x, -1
1323  %ny = xor i8 %y, -1
1324  %nz = xor i8 %z, -1
1325  call void @use(i8 %nx)
1326  call void @use(i8 %ny)
1327  call void @use(i8 %nz)
1328  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1329  %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1330  call void @use(i8 %m2)
1331  %not = xor i8 %m2, -1
1332  ret i8 %not
1333}
1334
1335define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {
1336; CHECK-LABEL: @freeToInvert_use3(
1337; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1338; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1339; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1340; CHECK-NEXT:    call void @use(i8 [[NX]])
1341; CHECK-NEXT:    call void @use(i8 [[NY]])
1342; CHECK-NEXT:    call void @use(i8 [[NZ]])
1343; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1344; CHECK-NEXT:    call void @use(i8 [[M1]])
1345; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1346; CHECK-NEXT:    call void @use(i8 [[M2]])
1347; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1348; CHECK-NEXT:    ret i8 [[NOT]]
1349;
1350  %nx = xor i8 %x, -1
1351  %ny = xor i8 %y, -1
1352  %nz = xor i8 %z, -1
1353  call void @use(i8 %nx)
1354  call void @use(i8 %ny)
1355  call void @use(i8 %nz)
1356  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1357  call void @use(i8 %m1)
1358  %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1359  call void @use(i8 %m2)
1360  %not = xor i8 %m2, -1
1361  ret i8 %not
1362}
1363
1364define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) {
1365; CHECK-LABEL: @freeToInvert_two_minmax_ops(
1366; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1367; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1368; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1369; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1370; CHECK-NEXT:    call void @use(i8 [[NX]])
1371; CHECK-NEXT:    call void @use(i8 [[NY]])
1372; CHECK-NEXT:    call void @use(i8 [[NZ]])
1373; CHECK-NEXT:    call void @use(i8 [[NW]])
1374; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1375; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]])
1376; CHECK-NEXT:    [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]])
1377; CHECK-NEXT:    ret i8 [[NOT]]
1378;
1379  %nx = xor i8 %x, -1
1380  %ny = xor i8 %y, -1
1381  %nz = xor i8 %z, -1
1382  %nw = xor i8 %w, -1
1383  call void @use(i8 %nx)
1384  call void @use(i8 %ny)
1385  call void @use(i8 %nz)
1386  call void @use(i8 %nw)
1387  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1388  %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1389  %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1390  %not = xor i8 %m3, -1
1391  ret i8 %not
1392}
1393
1394define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) {
1395; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1(
1396; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1397; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1398; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1399; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1400; CHECK-NEXT:    call void @use(i8 [[NX]])
1401; CHECK-NEXT:    call void @use(i8 [[NY]])
1402; CHECK-NEXT:    call void @use(i8 [[NZ]])
1403; CHECK-NEXT:    call void @use(i8 [[NW]])
1404; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1405; CHECK-NEXT:    call void @use(i8 [[M1]])
1406; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1407; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1408; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1409; CHECK-NEXT:    ret i8 [[NOT]]
1410;
1411  %nx = xor i8 %x, -1
1412  %ny = xor i8 %y, -1
1413  %nz = xor i8 %z, -1
1414  %nw = xor i8 %w, -1
1415  call void @use(i8 %nx)
1416  call void @use(i8 %ny)
1417  call void @use(i8 %nz)
1418  call void @use(i8 %nw)
1419  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1420  call void @use(i8 %m1)
1421  %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1422  %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1423  %not = xor i8 %m3, -1
1424  ret i8 %not
1425}
1426
1427define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) {
1428; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2(
1429; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1430; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1431; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1432; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1433; CHECK-NEXT:    call void @use(i8 [[NX]])
1434; CHECK-NEXT:    call void @use(i8 [[NY]])
1435; CHECK-NEXT:    call void @use(i8 [[NZ]])
1436; CHECK-NEXT:    call void @use(i8 [[NW]])
1437; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1438; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1439; CHECK-NEXT:    call void @use(i8 [[M2]])
1440; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1441; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1442; CHECK-NEXT:    ret i8 [[NOT]]
1443;
1444  %nx = xor i8 %x, -1
1445  %ny = xor i8 %y, -1
1446  %nz = xor i8 %z, -1
1447  %nw = xor i8 %w, -1
1448  call void @use(i8 %nx)
1449  call void @use(i8 %ny)
1450  call void @use(i8 %nz)
1451  call void @use(i8 %nw)
1452  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1453  %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1454  call void @use(i8 %m2)
1455  %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1456  %not = xor i8 %m3, -1
1457  ret i8 %not
1458}
1459
1460define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
1461; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3(
1462; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1463; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1464; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1465; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1466; CHECK-NEXT:    call void @use(i8 [[NX]])
1467; CHECK-NEXT:    call void @use(i8 [[NY]])
1468; CHECK-NEXT:    call void @use(i8 [[NZ]])
1469; CHECK-NEXT:    call void @use(i8 [[NW]])
1470; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1471; CHECK-NEXT:    call void @use(i8 [[M1]])
1472; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1473; CHECK-NEXT:    call void @use(i8 [[M2]])
1474; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1475; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1476; CHECK-NEXT:    ret i8 [[NOT]]
1477;
1478  %nx = xor i8 %x, -1
1479  %ny = xor i8 %y, -1
1480  %nz = xor i8 %z, -1
1481  %nw = xor i8 %w, -1
1482  call void @use(i8 %nx)
1483  call void @use(i8 %ny)
1484  call void @use(i8 %nz)
1485  call void @use(i8 %nw)
1486  %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1487  call void @use(i8 %m1)
1488  %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1489  call void @use(i8 %m2)
1490  %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1491  %not = xor i8 %m3, -1
1492  ret i8 %not
1493}
1494
1495define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) {
1496; CHECK-LABEL: @sub_not_min_max(
1497; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1498; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1499; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1500; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1501; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G]])
1502; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1503; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1504; CHECK-NEXT:    ret i8 [[CK]]
1505;
1506  %notr = xor i8 %r, -1
1507  %notg = xor i8 %g, -1
1508  call void @use(i8 %notg)
1509  %notb = xor i8 %b, -1
1510  call void @use(i8 %notb)
1511  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1512  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1513  %ck = sub i8 %notr, %k
1514  ret i8 %ck
1515}
1516
1517define i8 @sub_not_min_max_uses1(i8 %r, i8 %g, i8 %b) {
1518; CHECK-LABEL: @sub_not_min_max_uses1(
1519; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1520; CHECK-NEXT:    call void @use(i8 [[NOTR]])
1521; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1522; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1523; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1524; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1525; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R]], i8 [[G]])
1526; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1527; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1528; CHECK-NEXT:    ret i8 [[CK]]
1529;
1530  %notr = xor i8 %r, -1
1531  call void @use(i8 %notr)
1532  %notg = xor i8 %g, -1
1533  call void @use(i8 %notg)
1534  %notb = xor i8 %b, -1
1535  call void @use(i8 %notb)
1536  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1537  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1538  %ck = sub i8 %notr, %k
1539  ret i8 %ck
1540}
1541
1542define i8 @sub_not_min_max_uses2(i8 %r, i8 %g, i8 %b) {
1543; CHECK-LABEL: @sub_not_min_max_uses2(
1544; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1545; CHECK-NEXT:    call void @use(i8 [[NOTR]])
1546; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1547; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1548; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1549; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1550; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1551; CHECK-NEXT:    call void @use(i8 [[M]])
1552; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1553; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1554; CHECK-NEXT:    ret i8 [[CK]]
1555;
1556  %notr = xor i8 %r, -1
1557  call void @use(i8 %notr)
1558  %notg = xor i8 %g, -1
1559  call void @use(i8 %notg)
1560  %notb = xor i8 %b, -1
1561  call void @use(i8 %notb)
1562  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1563  call void @use(i8 %m)
1564  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1565  %ck = sub i8 %notr, %k
1566  ret i8 %ck
1567}
1568
1569declare void @use4(i8, i8, i8, i8)
1570
1571define void @cmyk(i8 %r, i8 %g, i8 %b) {
1572; CHECK-LABEL: @cmyk(
1573; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1574; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1575; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1576; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1577; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1578; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1579; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1580; CHECK-NEXT:    ret void
1581;
1582  %notr = xor i8 %r, -1
1583  %notg = xor i8 %g, -1
1584  %notb = xor i8 %b, -1
1585  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1586  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1587  %ck = sub i8 %notr, %k
1588  %mk = sub i8 %notg, %k
1589  %yk = sub i8 %notb, %k
1590  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1591  ret void
1592}
1593
1594; Same as above, but flip the operands of %k.
1595
1596define void @cmyk_commute1(i8 %r, i8 %g, i8 %b) {
1597; CHECK-LABEL: @cmyk_commute1(
1598; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1599; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1600; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1601; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1602; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1603; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1604; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1605; CHECK-NEXT:    ret void
1606;
1607  %notr = xor i8 %r, -1
1608  %notg = xor i8 %g, -1
1609  %notb = xor i8 %b, -1
1610  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1611  %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1612  %ck = sub i8 %notr, %k
1613  %mk = sub i8 %notg, %k
1614  %yk = sub i8 %notb, %k
1615  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1616  ret void
1617}
1618
1619; Same as above, but also flip the operands of %m.
1620
1621define void @cmyk_commute2(i8 %r, i8 %g, i8 %b) {
1622; CHECK-LABEL: @cmyk_commute2(
1623; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1624; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1625; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1626; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1627; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1628; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1629; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1630; CHECK-NEXT:    ret void
1631;
1632  %notr = xor i8 %r, -1
1633  %notg = xor i8 %g, -1
1634  %notb = xor i8 %b, -1
1635  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1636  %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1637  %ck = sub i8 %notr, %k
1638  %mk = sub i8 %notg, %k
1639  %yk = sub i8 %notb, %k
1640  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1641  ret void
1642}
1643
1644; Same as original, but only flip the operands of %m.
1645
1646define void @cmyk_commute3(i8 %r, i8 %g, i8 %b) {
1647; CHECK-LABEL: @cmyk_commute3(
1648; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1649; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1650; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1651; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1652; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1653; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1654; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1655; CHECK-NEXT:    ret void
1656;
1657  %notr = xor i8 %r, -1
1658  %notg = xor i8 %g, -1
1659  %notb = xor i8 %b, -1
1660  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1661  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1662  %ck = sub i8 %notr, %k
1663  %mk = sub i8 %notg, %k
1664  %yk = sub i8 %notb, %k
1665  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1666  ret void
1667}
1668
1669; Not exactly a commute, but make sure order of folds doesn't change anything.
1670; Also verify that we don't need matching min/max ops.
1671
1672define void @cmyk_commute4(i8 %r, i8 %g, i8 %b) {
1673; CHECK-LABEL: @cmyk_commute4(
1674; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1675; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1676; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1677; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1678; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1679; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1680; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1681; CHECK-NEXT:    ret void
1682;
1683  %notr = xor i8 %r, -1
1684  %notg = xor i8 %g, -1
1685  %notb = xor i8 %b, -1
1686  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1687  %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1688  %yk = sub i8 %notb, %k
1689  %ck = sub i8 %notr, %k
1690  %mk = sub i8 %notg, %k
1691  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1692  ret void
1693}
1694
1695; Not exactly a commute, but make sure order of folds doesn't change anything.
1696; Also verify that we don't need matching min/max ops.
1697
1698define void @cmyk_commute5(i8 %r, i8 %g, i8 %b) {
1699; CHECK-LABEL: @cmyk_commute5(
1700; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1701; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1702; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1703; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1704; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1705; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1706; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1707; CHECK-NEXT:    ret void
1708;
1709  %notr = xor i8 %r, -1
1710  %notg = xor i8 %g, -1
1711  %notb = xor i8 %b, -1
1712  %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1713  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1714  %ck = sub i8 %notr, %k
1715  %yk = sub i8 %notb, %k
1716  %mk = sub i8 %notg, %k
1717  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1718  ret void
1719}
1720
1721define void @cmyk_commute6(i8 %r, i8 %g, i8 %b) {
1722; CHECK-LABEL: @cmyk_commute6(
1723; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1724; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1725; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1726; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1727; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1728; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1729; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1730; CHECK-NEXT:    ret void
1731;
1732  %notr = xor i8 %r, -1
1733  %notg = xor i8 %g, -1
1734  %notb = xor i8 %b, -1
1735  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1736  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1737  %ck = sub i8 %k, %notr
1738  %mk = sub i8 %k, %notg
1739  %yk = sub i8 %k, %notb
1740  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1741  ret void
1742}
1743
1744; Same as above, but flip the operands of %k.
1745
1746define void @cmyk_commute7(i8 %r, i8 %g, i8 %b) {
1747; CHECK-LABEL: @cmyk_commute7(
1748; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1749; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1750; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1751; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1752; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1753; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1754; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1755; CHECK-NEXT:    ret void
1756;
1757  %notr = xor i8 %r, -1
1758  %notg = xor i8 %g, -1
1759  %notb = xor i8 %b, -1
1760  %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1761  %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1762  %ck = sub i8 %k, %notr
1763  %mk = sub i8 %k, %notg
1764  %yk = sub i8 %k, %notb
1765  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1766  ret void
1767}
1768
1769; Same as above, but also flip the operands of %m.
1770
1771define void @cmyk_commute8(i8 %r, i8 %g, i8 %b) {
1772; CHECK-LABEL: @cmyk_commute8(
1773; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1774; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1775; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1776; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1777; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1778; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1779; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1780; CHECK-NEXT:    ret void
1781;
1782  %notr = xor i8 %r, -1
1783  %notg = xor i8 %g, -1
1784  %notb = xor i8 %b, -1
1785  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1786  %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1787  %ck = sub i8 %k, %notr
1788  %mk = sub i8 %k, %notg
1789  %yk = sub i8 %k, %notb
1790  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1791  ret void
1792}
1793
1794; Same as original, but only flip the operands of %m.
1795
1796define void @cmyk_commute9(i8 %r, i8 %g, i8 %b) {
1797; CHECK-LABEL: @cmyk_commute9(
1798; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1799; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1800; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1801; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1802; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1803; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1804; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1805; CHECK-NEXT:    ret void
1806;
1807  %notr = xor i8 %r, -1
1808  %notg = xor i8 %g, -1
1809  %notb = xor i8 %b, -1
1810  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1811  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1812  %ck = sub i8 %k, %notr
1813  %mk = sub i8 %k, %notg
1814  %yk = sub i8 %k, %notb
1815  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1816  ret void
1817}
1818
1819; Not exactly a commute, but make sure order of folds doesn't change anything.
1820; Also verify that we don't need matching min/max ops.
1821
1822define void @cmyk_commute10(i8 %r, i8 %g, i8 %b) {
1823; CHECK-LABEL: @cmyk_commute10(
1824; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1825; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1826; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1827; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1828; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1829; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1830; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1831; CHECK-NEXT:    ret void
1832;
1833  %notr = xor i8 %r, -1
1834  %notg = xor i8 %g, -1
1835  %notb = xor i8 %b, -1
1836  %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1837  %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1838  %yk = sub i8 %notb, %k
1839  %ck = sub i8 %k, %notr
1840  %mk = sub i8 %notg, %k
1841  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1842  ret void
1843}
1844
1845; Not exactly a commute, but make sure order of folds doesn't change anything.
1846; Also verify that we don't need matching min/max ops.
1847
1848define void @cmyk_commute11(i8 %r, i8 %g, i8 %b) {
1849; CHECK-LABEL: @cmyk_commute11(
1850; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1851; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1852; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1853; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1854; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1855; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1856; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1857; CHECK-NEXT:    ret void
1858;
1859  %notr = xor i8 %r, -1
1860  %notg = xor i8 %g, -1
1861  %notb = xor i8 %b, -1
1862  %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1863  %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1864  %ck = sub i8 %notr, %k
1865  %yk = sub i8 %k, %notb
1866  %mk = sub i8 %k, %notg
1867  call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1868  ret void
1869}
1870
1871define i8 @smax_offset(i8 %x) {
1872; CHECK-LABEL: @smax_offset(
1873; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -127)
1874; CHECK-NEXT:    [[M:%.*]] = add nsw i8 [[TMP1]], 3
1875; CHECK-NEXT:    ret i8 [[M]]
1876;
1877  %a = add nsw i8 %x, 3
1878  %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1879  ret i8 %m
1880}
1881
1882; This is handled by InstSimplify; testing here to confirm assert.
1883
1884define i8 @smax_offset_limit(i8 %x) {
1885; CHECK-LABEL: @smax_offset_limit(
1886; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1887; CHECK-NEXT:    ret i8 [[A]]
1888;
1889  %a = add nsw i8 %x, 3
1890  %m = call i8 @llvm.smax.i8(i8 %a, i8 -125)
1891  ret i8 %m
1892}
1893
1894; This is handled by InstSimplify; testing here to confirm assert.
1895
1896define i8 @smax_offset_overflow(i8 %x) {
1897; CHECK-LABEL: @smax_offset_overflow(
1898; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1899; CHECK-NEXT:    ret i8 [[A]]
1900;
1901  %a = add nsw i8 %x, 3
1902  %m = call i8 @llvm.smax.i8(i8 %a, i8 -126)
1903  ret i8 %m
1904}
1905
1906; negative test - require nsw
1907
1908define i8 @smax_offset_may_wrap(i8 %x) {
1909; CHECK-LABEL: @smax_offset_may_wrap(
1910; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], 3
1911; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1912; CHECK-NEXT:    ret i8 [[M]]
1913;
1914  %a = add i8 %x, 3
1915  %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1916  ret i8 %m
1917}
1918
1919; negative test
1920
1921define i8 @smax_offset_uses(i8 %x) {
1922; CHECK-LABEL: @smax_offset_uses(
1923; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1924; CHECK-NEXT:    call void @use(i8 [[A]])
1925; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1926; CHECK-NEXT:    ret i8 [[M]]
1927;
1928  %a = add nsw i8 %x, 3
1929  call void @use(i8 %a)
1930  %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1931  ret i8 %m
1932}
1933
1934define <3 x i8> @smin_offset(<3 x i8> %x) {
1935; CHECK-LABEL: @smin_offset(
1936; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 -127))
1937; CHECK-NEXT:    [[M:%.*]] = or disjoint <3 x i8> [[TMP1]], splat (i8 124)
1938; CHECK-NEXT:    ret <3 x i8> [[M]]
1939;
1940  %a = add nsw nuw <3 x i8> %x, <i8 124, i8 124, i8 124>
1941  %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %a, <3 x i8> <i8 -3, i8 -3, i8 -3>)
1942  ret <3 x i8> %m
1943}
1944
1945; This is handled by InstSimplify; testing here to confirm assert.
1946
1947define i8 @smin_offset_limit(i8 %x) {
1948; CHECK-LABEL: @smin_offset_limit(
1949; CHECK-NEXT:    ret i8 -3
1950;
1951  %a = add nsw i8 %x, 125
1952  %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1953  ret i8 %m
1954}
1955
1956; This is handled by InstSimplify; testing here to confirm assert.
1957
1958define i8 @smin_offset_overflow(i8 %x) {
1959; CHECK-LABEL: @smin_offset_overflow(
1960; CHECK-NEXT:    ret i8 -3
1961;
1962  %a = add nsw i8 %x, 126
1963  %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1964  ret i8 %m
1965}
1966
1967; negative test - require nsw
1968
1969define i8 @smin_offset_may_wrap(i8 %x) {
1970; CHECK-LABEL: @smin_offset_may_wrap(
1971; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 124
1972; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1973; CHECK-NEXT:    ret i8 [[M]]
1974;
1975  %a = add nuw i8 %x, 124
1976  %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1977  ret i8 %m
1978}
1979
1980; negative test
1981
1982define i8 @smin_offset_uses(i8 %x) {
1983; CHECK-LABEL: @smin_offset_uses(
1984; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 124
1985; CHECK-NEXT:    call void @use(i8 [[A]])
1986; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1987; CHECK-NEXT:    ret i8 [[M]]
1988;
1989  %a = add nsw i8 %x, 124
1990  call void @use(i8 %a)
1991  %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1992  ret i8 %m
1993}
1994
1995; Note: 'nsw' must not propagate here.
1996
1997define <3 x i8> @umax_offset(<3 x i8> %x) {
1998; CHECK-LABEL: @umax_offset(
1999; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 3))
2000; CHECK-NEXT:    [[M:%.*]] = add nuw <3 x i8> [[TMP1]], splat (i8 127)
2001; CHECK-NEXT:    ret <3 x i8> [[M]]
2002;
2003  %a = add nsw nuw <3 x i8> %x, <i8 127, i8 127, i8 127>
2004  %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 130, i8 130, i8 130>)
2005  ret <3 x i8> %m
2006}
2007
2008; This is handled by InstSimplify; testing here to confirm assert.
2009
2010define i8 @umax_offset_limit(i8 %x) {
2011; CHECK-LABEL: @umax_offset_limit(
2012; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2013; CHECK-NEXT:    ret i8 [[A]]
2014;
2015  %a = add nuw i8 %x, 3
2016  %m = call i8 @llvm.umax.i8(i8 %a, i8 3)
2017  ret i8 %m
2018}
2019
2020; This is handled by InstSimplify; testing here to confirm assert.
2021
2022define i8 @umax_offset_overflow(i8 %x) {
2023; CHECK-LABEL: @umax_offset_overflow(
2024; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2025; CHECK-NEXT:    ret i8 [[A]]
2026;
2027  %a = add nuw i8 %x, 3
2028  %m = call i8 @llvm.umax.i8(i8 %a, i8 2)
2029  ret i8 %m
2030}
2031
2032; negative test - require nuw
2033
2034define i8 @umax_offset_may_wrap(i8 %x) {
2035; CHECK-LABEL: @umax_offset_may_wrap(
2036; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], 3
2037; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2038; CHECK-NEXT:    ret i8 [[M]]
2039;
2040  %a = add i8 %x, 3
2041  %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2042  ret i8 %m
2043}
2044
2045; negative test
2046
2047define i8 @umax_offset_uses(i8 %x) {
2048; CHECK-LABEL: @umax_offset_uses(
2049; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2050; CHECK-NEXT:    call void @use(i8 [[A]])
2051; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2052; CHECK-NEXT:    ret i8 [[M]]
2053;
2054  %a = add nuw i8 %x, 3
2055  call void @use(i8 %a)
2056  %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2057  ret i8 %m
2058}
2059
2060define i8 @umin_offset(i8 %x) {
2061; CHECK-LABEL: @umin_offset(
2062; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[X:%.*]], 0
2063; CHECK-NEXT:    [[M:%.*]] = select i1 [[DOTNOT]], i8 -5, i8 -4
2064; CHECK-NEXT:    ret i8 [[M]]
2065;
2066  %a = add nuw i8 %x, 251
2067  %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2068  ret i8 %m
2069}
2070
2071; This is handled by InstSimplify; testing here to confirm assert.
2072
2073define i8 @umin_offset_limit(i8 %x) {
2074; CHECK-LABEL: @umin_offset_limit(
2075; CHECK-NEXT:    ret i8 -4
2076;
2077  %a = add nuw i8 %x, 252
2078  %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2079  ret i8 %m
2080}
2081
2082; This is handled by InstSimplify; testing here to confirm assert.
2083
2084define i8 @umin_offset_overflow(i8 %x) {
2085; CHECK-LABEL: @umin_offset_overflow(
2086; CHECK-NEXT:    ret i8 -4
2087;
2088  %a = add nuw i8 %x, 253
2089  %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2090  ret i8 %m
2091}
2092
2093; negative test - require nuw
2094
2095define i8 @umin_offset_may_wrap(i8 %x) {
2096; CHECK-LABEL: @umin_offset_may_wrap(
2097; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], -5
2098; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2099; CHECK-NEXT:    ret i8 [[M]]
2100;
2101  %a = add nsw i8 %x, 251
2102  %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2103  ret i8 %m
2104}
2105
2106; negative test
2107
2108define i8 @umin_offset_uses(i8 %x) {
2109; CHECK-LABEL: @umin_offset_uses(
2110; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], -5
2111; CHECK-NEXT:    call void @use(i8 [[A]])
2112; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2113; CHECK-NEXT:    ret i8 [[M]]
2114;
2115  %a = add nuw i8 %x, 251
2116  call void @use(i8 %a)
2117  %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2118  ret i8 %m
2119}
2120
2121; TODO: This could transform
2122
2123define <3 x i8> @umax_vector_splat_poison(<3 x i8> %x) {
2124; CHECK-LABEL: @umax_vector_splat_poison(
2125; CHECK-NEXT:    [[A:%.*]] = add nuw <3 x i8> [[X:%.*]], <i8 poison, i8 64, i8 64>
2126; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[A]], <3 x i8> <i8 13, i8 -126, i8 -126>)
2127; CHECK-NEXT:    ret <3 x i8> [[R]]
2128;
2129  %a = add nuw <3 x i8> %x, <i8 poison, i8 64, i8 64>
2130  %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 13, i8 130, i8 130>)
2131  ret <3 x i8> %r
2132}
2133
2134; Issue #52884 - this would assert because of a failure to simplify.
2135
2136define i8 @smax_offset_simplify(i8 %x) {
2137; CHECK-LABEL: @smax_offset_simplify(
2138; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i8 [[X:%.*]], 50
2139; CHECK-NEXT:    ret i8 [[TMP1]]
2140;
2141  %1 = add nuw nsw i8 50, %x
2142  %m = call i8 @llvm.smax.i8(i8 %1, i8 -124)
2143  ret i8 %m
2144}
2145
2146define <3 x i8> @smax_smax_reassoc_constants(<3 x i8> %x) {
2147; CHECK-LABEL: @smax_smax_reassoc_constants(
2148; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 43, i8 44>)
2149; CHECK-NEXT:    ret <3 x i8> [[M2]]
2150;
2151  %m1 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)
2152  %m2 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2153  ret <3 x i8> %m2
2154}
2155
2156define i8 @smin_smin_reassoc_constants(i8 %x) {
2157; CHECK-LABEL: @smin_smin_reassoc_constants(
2158; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -3)
2159; CHECK-NEXT:    ret i8 [[M2]]
2160;
2161  %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)
2162  %m2 = call i8 @llvm.smin.i8(i8 -3, i8 %m1)
2163  ret i8 %m2
2164}
2165
2166define <3 x i8> @umax_umax_reassoc_constants(<3 x i8> %x) {
2167; CHECK-LABEL: @umax_umax_reassoc_constants(
2168; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 -113, i8 poison>)
2169; CHECK-NEXT:    ret <3 x i8> [[M2]]
2170;
2171  %m1 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)
2172  %m2 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 143, i8 poison>)
2173  ret <3 x i8> %m2
2174}
2175
2176; extra use is ok
2177
2178define i8 @umin_umin_reassoc_constants(i8 %x) {
2179; CHECK-LABEL: @umin_umin_reassoc_constants(
2180; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -116)
2181; CHECK-NEXT:    call void @use(i8 [[M1]])
2182; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
2183; CHECK-NEXT:    ret i8 [[M2]]
2184;
2185  %m1 = call i8 @llvm.umin.i8(i8 140, i8 %x)
2186  call void @use(i8 %m1)
2187  %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)
2188  ret i8 %m2
2189}
2190
2191; negative test - must have matching intrinsics
2192
2193define i8 @smin_smax_reassoc_constants(i8 %x) {
2194; CHECK-LABEL: @smin_smax_reassoc_constants(
2195; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 97)
2196; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 -3)
2197; CHECK-NEXT:    ret i8 [[M2]]
2198;
2199  %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)
2200  %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 -3)
2201  ret i8 %m2
2202}
2203
2204define i8 @smax_smax_reassoc_constant(i8 %x, i8 %y) {
2205; CHECK-LABEL: @smax_smax_reassoc_constant(
2206; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2207; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42)
2208; CHECK-NEXT:    ret i8 [[M2]]
2209;
2210  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
2211  %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 42)
2212  ret i8 %m2
2213}
2214
2215define <3 x i8> @smin_smin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) {
2216; CHECK-LABEL: @smin_smin_reassoc_constant(
2217; CHECK-NEXT:    [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2218; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2219; CHECK-NEXT:    ret <3 x i8> [[M2]]
2220;
2221  %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %y)
2222  %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2223  ret <3 x i8> %m2
2224}
2225
2226define i8 @umax_umax_reassoc_constant(i8 %x, i8 %y) {
2227; CHECK-LABEL: @umax_umax_reassoc_constant(
2228; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2229; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2230; CHECK-NEXT:    ret i8 [[M2]]
2231;
2232  %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
2233  %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 42)
2234  ret i8 %m2
2235}
2236
2237define <3 x i8> @umin_umin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) {
2238; CHECK-LABEL: @umin_umin_reassoc_constant(
2239; CHECK-NEXT:    [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2240; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2241; CHECK-NEXT:    ret <3 x i8> [[M2]]
2242;
2243  %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> %y)
2244  %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2245  ret <3 x i8> %m2
2246}
2247
2248define i8 @umin_umin_reassoc_constant_use(i8 %x, i8 %y) {
2249; CHECK-LABEL: @umin_umin_reassoc_constant_use(
2250; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2251; CHECK-NEXT:    call void @use(i8 [[M1]])
2252; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 42)
2253; CHECK-NEXT:    ret i8 [[M2]]
2254;
2255  %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
2256  call void @use(i8 %m1)
2257  %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)
2258  ret i8 %m2
2259}
2260
2261define i8 @smax_smax_reassoc_constant_sink(i8 %x, i8 %y) {
2262; CHECK-LABEL: @smax_smax_reassoc_constant_sink(
2263; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2264; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42)
2265; CHECK-NEXT:    ret i8 [[M2]]
2266;
2267  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2268  %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)
2269  ret i8 %m2
2270}
2271
2272define <3 x i8> @smin_smin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) {
2273; CHECK-LABEL: @smin_smin_reassoc_constant_sink(
2274; CHECK-NEXT:    [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2275; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2276; CHECK-NEXT:    ret <3 x i8> [[M2]]
2277;
2278  %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)
2279  %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %y)
2280  ret <3 x i8> %m2
2281}
2282
2283define i8 @umax_umax_reassoc_constant_sink(i8 %x, i8 %y) {
2284; CHECK-LABEL: @umax_umax_reassoc_constant_sink(
2285; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2286; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2287; CHECK-NEXT:    ret i8 [[M2]]
2288;
2289  %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)
2290  %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 %y)
2291  ret i8 %m2
2292}
2293
2294define <3 x i8> @umin_umin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) {
2295; CHECK-LABEL: @umin_umin_reassoc_constant_sink(
2296; CHECK-NEXT:    [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2297; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2298; CHECK-NEXT:    ret <3 x i8> [[M2]]
2299;
2300  %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)
2301  %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> %y)
2302  ret <3 x i8> %m2
2303}
2304
2305define i8 @umin_umin_reassoc_constant_sink_use(i8 %x, i8 %y) {
2306; CHECK-LABEL: @umin_umin_reassoc_constant_sink_use(
2307; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 42)
2308; CHECK-NEXT:    call void @use(i8 [[M1]])
2309; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[Y:%.*]])
2310; CHECK-NEXT:    ret i8 [[M2]]
2311;
2312  %m1 = call i8 @llvm.umin.i8(i8 %x, i8 42)
2313  call void @use(i8 %m1)
2314  %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %y)
2315  ret i8 %m2
2316}
2317
2318define i8 @smax_smax_smax_reassoc_constants(i8 %x, i8 %y) {
2319; CHECK-LABEL: @smax_smax_smax_reassoc_constants(
2320; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2321; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126)
2322; CHECK-NEXT:    ret i8 [[M3]]
2323;
2324  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2325  %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %m1)
2326  %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)
2327  ret i8 %m3
2328}
2329
2330define i8 @smax_smax_smax_reassoc_constants_swap(i8 %x, i8 %y) {
2331; CHECK-LABEL: @smax_smax_smax_reassoc_constants_swap(
2332; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2333; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126)
2334; CHECK-NEXT:    ret i8 [[M3]]
2335;
2336  %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2337  %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)
2338  %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)
2339  ret i8 %m3
2340}
2341
2342define i8 @smin_smin_smin_reassoc_constants(i8 %x, i8 %y) {
2343; CHECK-LABEL: @smin_smin_smin_reassoc_constants(
2344; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2345; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 42)
2346; CHECK-NEXT:    ret i8 [[M2]]
2347;
2348  %m1 = call i8 @llvm.smin.i8(i8 %x, i8 42)
2349  %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %m1)
2350  %m3 = call i8 @llvm.smin.i8(i8 %m2, i8 126)
2351  ret i8 %m3
2352}
2353
2354define i8 @umax_umax_reassoc_constantexpr_sink(i8 %x, i8 %y) {
2355; CHECK-LABEL: @umax_umax_reassoc_constantexpr_sink(
2356; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8))
2357; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2358; CHECK-NEXT:    ret i8 [[M2]]
2359;
2360  %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)
2361  %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8))
2362  ret i8 %m2
2363}
2364
2365define <3 x i8> @smax_unary_shuffle_ops(<3 x i8> %x, <3 x i8> %y) {
2366; CHECK-LABEL: @smax_unary_shuffle_ops(
2367; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2368; CHECK-NEXT:    [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2369; CHECK-NEXT:    ret <3 x i8> [[R]]
2370;
2371  %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2372  %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2373  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2374  ret <3 x i8> %r
2375}
2376
2377define <3 x i8> @smin_unary_shuffle_ops_use_poison_mask_elt(<3 x i8> %x, <3 x i8> %y) {
2378; CHECK-LABEL: @smin_unary_shuffle_ops_use_poison_mask_elt(
2379; CHECK-NEXT:    [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2380; CHECK-NEXT:    call void @use_vec(<3 x i8> [[SX]])
2381; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X]], <3 x i8> [[Y:%.*]])
2382; CHECK-NEXT:    [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2383; CHECK-NEXT:    ret <3 x i8> [[R]]
2384;
2385  %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2386  call void @use_vec(<3 x i8> %sx)
2387  %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2388  %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2389  ret <3 x i8> %r
2390}
2391
2392define <3 x i8> @umax_unary_shuffle_ops_use_widening(<2 x i8> %x, <2 x i8> %y) {
2393; CHECK-LABEL: @umax_unary_shuffle_ops_use_widening(
2394; CHECK-NEXT:    [[SY:%.*]] = shufflevector <2 x i8> [[Y:%.*]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2395; CHECK-NEXT:    call void @use_vec(<3 x i8> [[SY]])
2396; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.umax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y]])
2397; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2398; CHECK-NEXT:    ret <3 x i8> [[R]]
2399;
2400  %sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2401  %sy = shufflevector <2 x i8> %y, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2402  call void @use_vec(<3 x i8> %sy)
2403  %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2404  ret <3 x i8> %r
2405}
2406
2407define <3 x i8> @umin_unary_shuffle_ops_narrowing(<4 x i8> %x, <4 x i8> %y) {
2408; CHECK-LABEL: @umin_unary_shuffle_ops_narrowing(
2409; CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i8> @llvm.umin.v4i8(<4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]])
2410; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2411; CHECK-NEXT:    ret <3 x i8> [[R]]
2412;
2413  %sx = shufflevector <4 x i8> %x, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2414  %sy = shufflevector <4 x i8> %y, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2415  %r = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2416  ret <3 x i8> %r
2417}
2418
2419; negative test - must have 2 shuffles
2420
2421define <3 x i8> @smax_unary_shuffle_ops_unshuffled_op(<3 x i8> %x, <3 x i8> %y) {
2422; CHECK-LABEL: @smax_unary_shuffle_ops_unshuffled_op(
2423; CHECK-NEXT:    [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2424; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[Y:%.*]])
2425; CHECK-NEXT:    ret <3 x i8> [[R]]
2426;
2427  %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2428  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %y)
2429  ret <3 x i8> %r
2430}
2431
2432; negative test - must have identical masks
2433
2434define <3 x i8> @smax_unary_shuffle_ops_wrong_mask(<3 x i8> %x, <3 x i8> %y) {
2435; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_mask(
2436; CHECK-NEXT:    [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2437; CHECK-NEXT:    [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2438; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2439; CHECK-NEXT:    ret <3 x i8> [[R]]
2440;
2441  %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2442  %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2443  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2444  ret <3 x i8> %r
2445}
2446
2447; negative test - must be unary shuffles
2448
2449define <3 x i8> @smax_unary_shuffle_ops_wrong_shuf(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
2450; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_shuf(
2451; CHECK-NEXT:    [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]], <3 x i32> <i32 1, i32 0, i32 3>
2452; CHECK-NEXT:    [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> [[Z]], <3 x i32> <i32 1, i32 0, i32 3>
2453; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2454; CHECK-NEXT:    ret <3 x i8> [[R]]
2455;
2456  %sx = shufflevector <3 x i8> %x, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>
2457  %sy = shufflevector <3 x i8> %y, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>
2458  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2459  ret <3 x i8> %r
2460}
2461
2462; negative test - too many uses
2463
2464define <3 x i8> @smin_unary_shuffle_ops_uses(<3 x i8> %x, <3 x i8> %y) {
2465; CHECK-LABEL: @smin_unary_shuffle_ops_uses(
2466; CHECK-NEXT:    [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2467; CHECK-NEXT:    call void @use_vec(<3 x i8> [[SX]])
2468; CHECK-NEXT:    [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2469; CHECK-NEXT:    call void @use_vec(<3 x i8> [[SY]])
2470; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2471; CHECK-NEXT:    ret <3 x i8> [[R]]
2472;
2473  %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2474  call void @use_vec(<3 x i8> %sx)
2475  %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2476  call void @use_vec(<3 x i8> %sy)
2477  %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2478  ret <3 x i8> %r
2479}
2480
2481; This would assert/crash because we tried to zext to i1.
2482
2483@g = external dso_local global i32, align 4
2484
2485define i1 @PR57986() {
2486; CHECK-LABEL: @PR57986(
2487; CHECK-NEXT:    ret i1 ptrtoint (ptr @g to i1)
2488;
2489  %umin = call i1 @llvm.umin.i1(i1 ptrtoint (ptr @g to i1), i1 true)
2490  ret i1 %umin
2491}
2492
2493define i8 @fold_umax_with_knownbits_info(i8 %a, i8 %b) {
2494; CHECK-LABEL: @fold_umax_with_knownbits_info(
2495; CHECK-NEXT:  entry:
2496; CHECK-NEXT:    [[A1:%.*]] = or i8 [[A:%.*]], 1
2497; CHECK-NEXT:    [[A2:%.*]] = shl i8 [[B:%.*]], 1
2498; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2499; CHECK-NEXT:    ret i8 [[SUB]]
2500;
2501entry:
2502  %a1 = or i8 %a, 1
2503  %a2 = shl i8 %b, 1
2504  %sub = sub i8 %a1, %a2
2505  %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)
2506  ret i8 %val
2507}
2508
2509define <3 x i8> @fold_umax_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {
2510; CHECK-LABEL: @fold_umax_with_knownbits_info_poison_in_splat(
2511; CHECK-NEXT:  entry:
2512; CHECK-NEXT:    [[A1:%.*]] = or <3 x i8> [[A:%.*]], splat (i8 1)
2513; CHECK-NEXT:    [[A2:%.*]] = shl <3 x i8> [[B:%.*]], splat (i8 1)
2514; CHECK-NEXT:    [[SUB:%.*]] = sub <3 x i8> [[A1]], [[A2]]
2515; CHECK-NEXT:    ret <3 x i8> [[SUB]]
2516;
2517entry:
2518  %a1 = or <3 x i8> %a, <i8 1, i8 1, i8 1>
2519  %a2 = shl <3 x i8> %b, <i8 1, i8 1, i8 1>
2520  %sub = sub <3 x i8> %a1, %a2
2521  %val = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sub, <3 x i8> <i8 1, i8 poison, i8 1>)
2522  ret <3 x i8> %val
2523}
2524
2525define i8 @fold_umin_with_knownbits_info(i8 %a, i8 %b) {
2526; CHECK-LABEL: @fold_umin_with_knownbits_info(
2527; CHECK-NEXT:  entry:
2528; CHECK-NEXT:    ret i8 3
2529;
2530entry:
2531  %a1 = or i8 %a, 3
2532  %a2 = shl i8 %b, 2
2533  %sub = sub i8 %a1, %a2
2534  %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)
2535  ret i8 %val
2536}
2537
2538define <3 x i8> @fold_umin_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {
2539; CHECK-LABEL: @fold_umin_with_knownbits_info_poison_in_splat(
2540; CHECK-NEXT:  entry:
2541; CHECK-NEXT:    ret <3 x i8> splat (i8 3)
2542;
2543entry:
2544  %a1 = or <3 x i8> %a, <i8 3, i8 3, i8 3>
2545  %a2 = shl <3 x i8> %b, <i8 2, i8 2, i8 2>
2546  %sub = sub <3 x i8> %a1, %a2
2547  %val = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sub, <3 x i8> <i8 3, i8 poison, i8 3>)
2548  ret <3 x i8> %val
2549}
2550
2551define i8 @fold_umax_with_knownbits_info_fail(i8 %a, i8 %b) {
2552; CHECK-LABEL: @fold_umax_with_knownbits_info_fail(
2553; CHECK-NEXT:  entry:
2554; CHECK-NEXT:    [[A1:%.*]] = or i8 [[A:%.*]], 2
2555; CHECK-NEXT:    [[A2:%.*]] = shl i8 [[B:%.*]], 1
2556; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2557; CHECK-NEXT:    [[VAL:%.*]] = call i8 @llvm.umax.i8(i8 [[SUB]], i8 1)
2558; CHECK-NEXT:    ret i8 [[VAL]]
2559;
2560entry:
2561  %a1 = or i8 %a, 2
2562  %a2 = shl i8 %b, 1
2563  %sub = sub i8 %a1, %a2
2564  %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)
2565  ret i8 %val
2566}
2567
2568define i8 @fold_umin_with_knownbits_info_fail(i8 %a, i8 %b) {
2569; CHECK-LABEL: @fold_umin_with_knownbits_info_fail(
2570; CHECK-NEXT:  entry:
2571; CHECK-NEXT:    [[A1:%.*]] = or i8 [[A:%.*]], 1
2572; CHECK-NEXT:    [[A2:%.*]] = shl i8 [[B:%.*]], 2
2573; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2574; CHECK-NEXT:    [[VAL:%.*]] = call i8 @llvm.umin.i8(i8 [[SUB]], i8 3)
2575; CHECK-NEXT:    ret i8 [[VAL]]
2576;
2577entry:
2578  %a1 = or i8 %a, 1
2579  %a2 = shl i8 %b, 2
2580  %sub = sub i8 %a1, %a2
2581  %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)
2582  ret i8 %val
2583}
2584
2585define i8 @test_umax_and(i8 %x, i8 %y) {
2586; CHECK-LABEL: @test_umax_and(
2587; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2588; CHECK-NEXT:    [[RES1:%.*]] = and i8 [[RES]], -64
2589; CHECK-NEXT:    ret i8 [[RES1]]
2590;
2591  %x1 = and i8 %x, -64
2592  %y1 = and i8 %y, -64
2593  %res = call i8 @llvm.umax.i8(i8 %x1, i8 %y1)
2594  ret i8 %res
2595}
2596
2597define i8 @test_umin_and(i8 %x, i8 %y) {
2598; CHECK-LABEL: @test_umin_and(
2599; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.umin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2600; CHECK-NEXT:    [[RES1:%.*]] = and i8 [[RES]], -64
2601; CHECK-NEXT:    ret i8 [[RES1]]
2602;
2603  %x1 = and i8 %x, -64
2604  %y1 = and i8 %y, -64
2605  %res = call i8 @llvm.umin.i8(i8 %x1, i8 %y1)
2606  ret i8 %res
2607}
2608
2609define i8 @test_smax_and(i8 %x, i8 %y) {
2610; CHECK-LABEL: @test_smax_and(
2611; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.smax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2612; CHECK-NEXT:    [[RES1:%.*]] = and i8 [[RES]], -64
2613; CHECK-NEXT:    ret i8 [[RES1]]
2614;
2615  %x1 = and i8 %x, -64
2616  %y1 = and i8 %y, -64
2617  %res = call i8 @llvm.smax.i8(i8 %x1, i8 %y1)
2618  ret i8 %res
2619}
2620
2621define i8 @test_smin_and(i8 %x, i8 %y) {
2622; CHECK-LABEL: @test_smin_and(
2623; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2624; CHECK-NEXT:    [[RES1:%.*]] = and i8 [[RES]], -64
2625; CHECK-NEXT:    ret i8 [[RES1]]
2626;
2627  %x1 = and i8 %x, -64
2628  %y1 = and i8 %y, -64
2629  %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2630  ret i8 %res
2631}
2632
2633define i8 @test_smin_and_mismatch(i8 %x, i8 %y) {
2634; CHECK-LABEL: @test_smin_and_mismatch(
2635; CHECK-NEXT:    [[X1:%.*]] = and i8 [[X:%.*]], -64
2636; CHECK-NEXT:    [[Y1:%.*]] = and i8 [[Y:%.*]], -32
2637; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2638; CHECK-NEXT:    ret i8 [[RES]]
2639;
2640  %x1 = and i8 %x, -64
2641  %y1 = and i8 %y, -32
2642  %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2643  ret i8 %res
2644}
2645
2646define i8 @test_smin_and_non_negated_pow2(i8 %x, i8 %y) {
2647; CHECK-LABEL: @test_smin_and_non_negated_pow2(
2648; CHECK-NEXT:    [[X1:%.*]] = and i8 [[X:%.*]], 31
2649; CHECK-NEXT:    [[Y1:%.*]] = and i8 [[Y:%.*]], 31
2650; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2651; CHECK-NEXT:    ret i8 [[RES]]
2652;
2653  %x1 = and i8 %x, 31
2654  %y1 = and i8 %y, 31
2655  %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2656  ret i8 %res
2657}
2658
2659define i8 @test_smin_and_multiuse(i8 %x, i8 %y) {
2660; CHECK-LABEL: @test_smin_and_multiuse(
2661; CHECK-NEXT:    [[X1:%.*]] = and i8 [[X:%.*]], 31
2662; CHECK-NEXT:    [[Y1:%.*]] = and i8 [[Y:%.*]], 31
2663; CHECK-NEXT:    call void @use(i8 [[Y1]])
2664; CHECK-NEXT:    [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2665; CHECK-NEXT:    ret i8 [[RES]]
2666;
2667  %x1 = and i8 %x, 31
2668  %y1 = and i8 %y, 31
2669  call void @use(i8 %y1)
2670  %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2671  ret i8 %res
2672}
2673