[SLP] Add cost model for `llvm.powi.*` intrinsics
[llvm-project.git] / llvm / test / Transforms / InstCombine / minmax-intrinsics.ll
blob7fb4f80c5cadba177fcc017e032e9dfac4a82f87
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare i8 @llvm.umin.i8(i8, i8)
5 declare i8 @llvm.umax.i8(i8, i8)
6 declare i8 @llvm.smin.i8(i8, i8)
7 declare i8 @llvm.smax.i8(i8, i8)
8 declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)
9 declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)
10 declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)
11 declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)
12 declare void @use(i8)
13 declare void @use_vec(<3 x i8>)
15 define i8 @umin_known_bits(i8 %x, i8 %y) {
16 ; CHECK-LABEL: @umin_known_bits(
17 ; CHECK-NEXT:    ret i8 0
19   %x2 = and i8 %x, 127
20   %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y)
21   %r = and i8 %m, -128
22   ret i8 %r
25 define i8 @umax_known_bits(i8 %x, i8 %y) {
26 ; CHECK-LABEL: @umax_known_bits(
27 ; CHECK-NEXT:    ret i8 -128
29   %x2 = or i8 %x, -128
30   %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y)
31   %r = and i8 %m, -128
32   ret i8 %r
35 define i8 @smin_known_bits(i8 %x, i8 %y) {
36 ; CHECK-LABEL: @smin_known_bits(
37 ; CHECK-NEXT:    ret i8 -128
39   %x2 = or i8 %x, -128
40   %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y)
41   %r = and i8 %m, -128
42   ret i8 %r
45 define i8 @smax_known_bits(i8 %x, i8 %y) {
46 ; CHECK-LABEL: @smax_known_bits(
47 ; CHECK-NEXT:    ret i8 0
49   %x2 = and i8 %x, 127
50   %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y)
51   %r = and i8 %m, -128
52   ret i8 %r
55 define i8 @smax_sext(i5 %x, i5 %y) {
56 ; CHECK-LABEL: @smax_sext(
57 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
58 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
59 ; CHECK-NEXT:    ret i8 [[M]]
61   %sx = sext i5 %x to i8
62   %sy = sext i5 %y to i8
63   %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy)
64   ret i8 %m
67 ; Extra use is ok.
69 define i8 @smin_sext(i5 %x, i5 %y) {
70 ; CHECK-LABEL: @smin_sext(
71 ; CHECK-NEXT:    [[SY:%.*]] = sext i5 [[Y:%.*]] to i8
72 ; CHECK-NEXT:    call void @use(i8 [[SY]])
73 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Y]])
74 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
75 ; CHECK-NEXT:    ret i8 [[M]]
77   %sx = sext i5 %x to i8
78   %sy = sext i5 %y to i8
79   call void @use(i8 %sy)
80   %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy)
81   ret i8 %m
84 ; Sext doesn't change unsigned min/max comparison of narrow values.
86 define i8 @umax_sext(i5 %x, i5 %y) {
87 ; CHECK-LABEL: @umax_sext(
88 ; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
89 ; CHECK-NEXT:    call void @use(i8 [[SX]])
90 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X]], i5 [[Y:%.*]])
91 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
92 ; CHECK-NEXT:    ret i8 [[M]]
94   %sx = sext i5 %x to i8
95   call void @use(i8 %sx)
96   %sy = sext i5 %y to i8
97   %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy)
98   ret i8 %m
101 define <3 x i8> @umin_sext(<3 x i5> %x, <3 x i5> %y) {
102 ; CHECK-LABEL: @umin_sext(
103 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> [[Y:%.*]])
104 ; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
105 ; CHECK-NEXT:    ret <3 x i8> [[M]]
107   %sx = sext <3 x i5> %x to <3 x i8>
108   %sy = sext <3 x i5> %y to <3 x i8>
109   %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
110   ret <3 x i8> %m
113 ; Negative test - zext may change sign of inputs
115 define i8 @smax_zext(i5 %x, i5 %y) {
116 ; CHECK-LABEL: @smax_zext(
117 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
118 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
119 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]])
120 ; CHECK-NEXT:    ret i8 [[M]]
122   %zx = zext i5 %x to i8
123   %zy = zext i5 %y to i8
124   %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy)
125   ret i8 %m
128 ; Negative test - zext may change sign of inputs
130 define i8 @smin_zext(i5 %x, i5 %y) {
131 ; CHECK-LABEL: @smin_zext(
132 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
133 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
134 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]])
135 ; CHECK-NEXT:    ret i8 [[M]]
137   %zx = zext i5 %x to i8
138   %zy = zext i5 %y to i8
139   %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy)
140   ret i8 %m
143 define i8 @umax_zext(i5 %x, i5 %y) {
144 ; CHECK-LABEL: @umax_zext(
145 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
146 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
147 ; CHECK-NEXT:    ret i8 [[M]]
149   %zx = zext i5 %x to i8
150   %zy = zext i5 %y to i8
151   %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy)
152   ret i8 %m
155 define i8 @umin_zext(i5 %x, i5 %y) {
156 ; CHECK-LABEL: @umin_zext(
157 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
158 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
159 ; CHECK-NEXT:    ret i8 [[M]]
161   %zx = zext i5 %x to i8
162   %zy = zext i5 %y to i8
163   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
164   ret i8 %m
167 ; Negative test - mismatched types
169 define i8 @umin_zext_types(i6 %x, i5 %y) {
170 ; CHECK-LABEL: @umin_zext_types(
171 ; CHECK-NEXT:    [[ZX:%.*]] = zext i6 [[X:%.*]] to i8
172 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
173 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
174 ; CHECK-NEXT:    ret i8 [[M]]
176   %zx = zext i6 %x to i8
177   %zy = zext i5 %y to i8
178   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
179   ret i8 %m
182 ; Negative test - mismatched extends
184 define i8 @umin_ext(i5 %x, i5 %y) {
185 ; CHECK-LABEL: @umin_ext(
186 ; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
187 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
188 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]])
189 ; CHECK-NEXT:    ret i8 [[M]]
191   %sx = sext i5 %x to i8
192   %zy = zext i5 %y to i8
193   %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy)
194   ret i8 %m
197 ; Negative test - too many uses.
199 define i8 @umin_zext_uses(i5 %x, i5 %y) {
200 ; CHECK-LABEL: @umin_zext_uses(
201 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
202 ; CHECK-NEXT:    call void @use(i8 [[ZX]])
203 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
204 ; CHECK-NEXT:    call void @use(i8 [[ZY]])
205 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
206 ; CHECK-NEXT:    ret i8 [[M]]
208   %zx = zext i5 %x to i8
209   call void @use(i8 %zx)
210   %zy = zext i5 %y to i8
211   call void @use(i8 %zy)
212   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
213   ret i8 %m
216 define i8 @smax_sext_constant(i5 %x) {
217 ; CHECK-LABEL: @smax_sext_constant(
218 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
219 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
220 ; CHECK-NEXT:    ret i8 [[M]]
222   %e = sext i5 %x to i8
223   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
224   ret i8 %m
227 ; simplifies
229 define i8 @smax_sext_constant_big(i5 %x) {
230 ; CHECK-LABEL: @smax_sext_constant_big(
231 ; CHECK-NEXT:    ret i8 16
233   %e = sext i5 %x to i8
234   %m = call i8 @llvm.smax.i8(i8 %e, i8 16)
235   ret i8 %m
238 ; negative test
240 define i8 @smax_zext_constant(i5 %x) {
241 ; CHECK-LABEL: @smax_zext_constant(
242 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
243 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
244 ; CHECK-NEXT:    ret i8 [[M]]
246   %e = zext i5 %x to i8
247   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
248   ret i8 %m
251 define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
252 ; CHECK-LABEL: @smin_sext_constant(
253 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
254 ; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
255 ; CHECK-NEXT:    ret <3 x i8> [[M]]
257   %e = sext <3 x i5> %x to <3 x i8>
258   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>)
259   ret <3 x i8> %m
262 ; negative test
264 define i8 @smin_zext_constant(i5 %x) {
265 ; CHECK-LABEL: @smin_zext_constant(
266 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
267 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7)
268 ; CHECK-NEXT:    ret i8 [[M]]
270   %e = zext i5 %x to i8
271   %m = call i8 @llvm.smin.i8(i8 %e, i8 7)
272   ret i8 %m
275 define i8 @umax_sext_constant(i5 %x) {
276 ; CHECK-LABEL: @umax_sext_constant(
277 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
278 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
279 ; CHECK-NEXT:    ret i8 [[M]]
281   %e = sext i5 %x to i8
282   %m = call i8 @llvm.umax.i8(i8 %e, i8 7)
283   ret i8 %m
286 ; negative test
288 define i8 @umax_sext_constant_big(i5 %x) {
289 ; CHECK-LABEL: @umax_sext_constant_big(
290 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
291 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126)
292 ; CHECK-NEXT:    ret i8 [[M]]
294   %e = sext i5 %x to i8
295   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
296   ret i8 %m
299 define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
300 ; CHECK-LABEL: @umax_zext_constant(
301 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
302 ; CHECK-NEXT:    [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
303 ; CHECK-NEXT:    ret <3 x i8> [[M]]
305   %e = zext <3 x i5> %x to <3 x i8>
306   %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>)
307   ret <3 x i8> %m
310 ; simplifies
312 define i8 @umax_zext_constant_big(i5 %x) {
313 ; CHECK-LABEL: @umax_zext_constant_big(
314 ; CHECK-NEXT:    ret i8 126
316   %e = zext i5 %x to i8
317   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
318   ret i8 %m
321 define i8 @umin_sext_constant(i5 %x) {
322 ; CHECK-LABEL: @umin_sext_constant(
323 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
324 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
325 ; CHECK-NEXT:    ret i8 [[M]]
327   %e = sext i5 %x to i8
328   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
329   ret i8 %m
332 ; negative test
334 define i8 @umin_sext_constant_big(i5 %x) {
335 ; CHECK-LABEL: @umin_sext_constant_big(
336 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
337 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126)
338 ; CHECK-NEXT:    ret i8 [[M]]
340   %e = sext i5 %x to i8
341   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
342   ret i8 %m
345 define i8 @umin_zext_constant(i5 %x) {
346 ; CHECK-LABEL: @umin_zext_constant(
347 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
348 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
349 ; CHECK-NEXT:    ret i8 [[M]]
351   %e = zext i5 %x to i8
352   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
353   ret i8 %m
356 ; simplifies
358 define i8 @umin_zext_constant_big(i5 %x) {
359 ; CHECK-LABEL: @umin_zext_constant_big(
360 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
361 ; CHECK-NEXT:    ret i8 [[E]]
363   %e = zext i5 %x to i8
364   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
365   ret i8 %m
368 ; negative test
370 define i8 @umin_zext_constant_uses(i5 %x) {
371 ; CHECK-LABEL: @umin_zext_constant_uses(
372 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
373 ; CHECK-NEXT:    call void @use(i8 [[E]])
374 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
375 ; CHECK-NEXT:    ret i8 [[M]]
377   %e = zext i5 %x to i8
378   call void @use(i8 %e)
379   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
380   ret i8 %m
383 define i8 @smax_of_nots(i8 %x, i8 %y) {
384 ; CHECK-LABEL: @smax_of_nots(
385 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
386 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
387 ; CHECK-NEXT:    ret i8 [[M]]
389   %notx = xor i8 %x, -1
390   %noty = xor i8 %y, -1
391   %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
392   ret i8 %m
395 ; Vectors are ok (including undef lanes of not ops)
397 define <3 x i8> @smin_of_nots(<3 x i8> %x, <3 x i8> %y) {
398 ; CHECK-LABEL: @smin_of_nots(
399 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
400 ; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1>
401 ; CHECK-NEXT:    ret <3 x i8> [[M]]
403   %notx = xor <3 x i8> %x, <i8 -1, i8 undef, i8 -1>
404   %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 undef>
405   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty)
406   ret <3 x i8> %m
409 ; An extra use is ok.
411 define i8 @umax_of_nots(i8 %x, i8 %y) {
412 ; CHECK-LABEL: @umax_of_nots(
413 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
414 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
415 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]])
416 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
417 ; CHECK-NEXT:    ret i8 [[M]]
419   %notx = xor i8 %x, -1
420   call void @use(i8 %notx)
421   %noty = xor i8 %y, -1
422   %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty)
423   ret i8 %m
426 ; An extra use is ok.
428 define i8 @umin_of_nots(i8 %x, i8 %y) {
429 ; CHECK-LABEL: @umin_of_nots(
430 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
431 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
432 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y]])
433 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
434 ; CHECK-NEXT:    ret i8 [[M]]
436   %notx = xor i8 %x, -1
437   %noty = xor i8 %y, -1
438   call void @use(i8 %noty)
439   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
440   ret i8 %m
443 ; Negative test - too many uses
445 define i8 @umin_of_nots_uses(i8 %x, i8 %y) {
446 ; CHECK-LABEL: @umin_of_nots_uses(
447 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
448 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
449 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
450 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
451 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[NOTY]])
452 ; CHECK-NEXT:    ret i8 [[M]]
454   %notx = xor i8 %x, -1
455   call void @use(i8 %notx)
456   %noty = xor i8 %y, -1
457   call void @use(i8 %noty)
458   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
459   ret i8 %m
462 ; Canonicalize 'not' after min/max.
464 define i8 @smax_of_not_and_const(i8 %x) {
465 ; CHECK-LABEL: @smax_of_not_and_const(
466 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -43)
467 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
468 ; CHECK-NEXT:    ret i8 [[M]]
470   %notx = xor i8 %x, -1
471   %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)
472   ret i8 %m
475 ; Vectors are ok (including undef lanes of not ops and min/max constant operand)
477 define <3 x i8> @smin_of_not_and_const(<3 x i8> %x) {
478 ; CHECK-LABEL: @smin_of_not_and_const(
479 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -43, i8 undef, i8 -44>)
480 ; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1>
481 ; CHECK-NEXT:    ret <3 x i8> [[M]]
483   %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 undef>
484   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 undef, i8 43>, <3 x i8> %notx)
485   ret <3 x i8> %m
488 define i8 @umax_of_not_and_const(i8 %x) {
489 ; CHECK-LABEL: @umax_of_not_and_const(
490 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -45)
491 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
492 ; CHECK-NEXT:    ret i8 [[M]]
494   %notx = xor i8 %x, -1
495   %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)
496   ret i8 %m
499 define i8 @umin_of_not_and_const(i8 %x) {
500 ; CHECK-LABEL: @umin_of_not_and_const(
501 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 44)
502 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
503 ; CHECK-NEXT:    ret i8 [[M]]
505   %notx = xor i8 %x, -1
506   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
507   ret i8 %m
510 define i8 @umin_of_not_and_smax(i8 %x, i8 %y, i8 %z) {
511 ; CHECK-LABEL: @umin_of_not_and_smax(
512 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
513 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
514 ; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
515 ; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
516 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[Z]])
517 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[TMP1]])
518 ; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
519 ; CHECK-NEXT:    ret i8 [[M2]]
521   %notx = xor i8 %x, -1
522   %noty = xor i8 %y, -1
523   call void @use(i8 %noty)
524   %notz = xor i8 %z, -1
525   call void @use(i8 %notz)
526   %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz)
527   %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx)
528   ret i8 %m2
531 define i8 @smin_of_umax_and_not(i8 %x, i8 %y, i8 %z) {
532 ; CHECK-LABEL: @smin_of_umax_and_not(
533 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
534 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
535 ; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
536 ; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
537 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
538 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[TMP1]])
539 ; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
540 ; CHECK-NEXT:    ret i8 [[M2]]
542   %notx = xor i8 %x, -1
543   %noty = xor i8 %y, -1
544   call void @use(i8 %noty)
545   %notz = xor i8 %z, -1
546   call void @use(i8 %notz)
547   %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz)
548   %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1)
549   ret i8 %m2
552 ; Negative test - don't infinite loop on constant expression
554 define i8 @umin_of_not_and_nontrivial_const(i8 %x) {
555 ; CHECK-LABEL: @umin_of_not_and_nontrivial_const(
556 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
557 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (i8 (i8)* @umin_of_not_and_nontrivial_const to i8))
558 ; CHECK-NEXT:    ret i8 [[M]]
560   %notx = xor i8 %x, -1
561   %m = call i8 @llvm.umin.i8(i8 ptrtoint (i8(i8)* @umin_of_not_and_nontrivial_const to i8), i8 %notx)
562   ret i8 %m
565 ; Negative test - too many uses
567 define i8 @umin_of_not_and_const_uses(i8 %x) {
568 ; CHECK-LABEL: @umin_of_not_and_const_uses(
569 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
570 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
571 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45)
572 ; CHECK-NEXT:    ret i8 [[M]]
574   %notx = xor i8 %x, -1
575   call void @use(i8 %notx)
576   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
577   ret i8 %m
580 define i8 @not_smax_of_nots(i8 %x, i8 %y) {
581 ; CHECK-LABEL: @not_smax_of_nots(
582 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
583 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
584 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
585 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
586 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
587 ; CHECK-NEXT:    ret i8 [[TMP1]]
589   %notx = xor i8 %x, -1
590   call void @use(i8 %notx)
591   %noty = xor i8 %y, -1
592   call void @use(i8 %noty)
593   %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
594   %notm = xor i8 %m, -1
595   ret i8 %notm
598 define i8 @not_smin_of_nots(i8 %x, i8 %y) {
599 ; CHECK-LABEL: @not_smin_of_nots(
600 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
601 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
602 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
603 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
604 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]])
605 ; CHECK-NEXT:    call void @use(i8 [[M]])
606 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
607 ; CHECK-NEXT:    ret i8 [[NOTM]]
609   %notx = xor i8 %x, -1
610   call void @use(i8 %notx)
611   %noty = xor i8 %y, -1
612   call void @use(i8 %noty)
613   %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty)
614   call void @use(i8 %m)
615   %notm = xor i8 %m, -1
616   ret i8 %notm
619 define i8 @not_umax_of_not(i8 %x, i8 %y) {
620 ; CHECK-LABEL: @not_umax_of_not(
621 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
622 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
623 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
624 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])
625 ; CHECK-NEXT:    ret i8 [[TMP2]]
627   %notx = xor i8 %x, -1
628   call void @use(i8 %notx)
629   %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)
630   %notm = xor i8 %m, -1
631   ret i8 %notm
634 ; Negative test - this would require an extra instruction.
636 define i8 @not_umin_of_not(i8 %x, i8 %y) {
637 ; CHECK-LABEL: @not_umin_of_not(
638 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
639 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
640 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]])
641 ; CHECK-NEXT:    call void @use(i8 [[M]])
642 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
643 ; CHECK-NEXT:    ret i8 [[NOTM]]
645   %notx = xor i8 %x, -1
646   call void @use(i8 %notx)
647   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y)
648   call void @use(i8 %m)
649   %notm = xor i8 %m, -1
650   ret i8 %notm
653 define i8 @not_umin_of_not_constant_op(i8 %x) {
654 ; CHECK-LABEL: @not_umin_of_not_constant_op(
655 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
656 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
657 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43)
658 ; CHECK-NEXT:    ret i8 [[TMP1]]
660   %notx = xor i8 %x, -1
661   call void @use(i8 %notx)
662   %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)
663   %notm = xor i8 %m, -1
664   ret i8 %notm
667 define i8 @smax_negation(i8 %x, i8 %y) {
668 ; CHECK-LABEL: @smax_negation(
669 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
670 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
671 ; CHECK-NEXT:    ret i8 [[TMP1]]
673   %s1 = sub i8 %x, %y
674   %s2 = sub i8 %y, %x
675   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
676   ret i8 %r
679 define i8 @smax_negation_nsw(i8 %x, i8 %y) {
680 ; CHECK-LABEL: @smax_negation_nsw(
681 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
682 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
683 ; CHECK-NEXT:    ret i8 [[TMP1]]
685   %s1 = sub nsw i8 %x, %y
686   %s2 = sub nsw i8 %y, %x
687   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
688   ret i8 %r
691 define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
692 ; CHECK-LABEL: @smax_negation_not_nsw(
693 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
694 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
695 ; CHECK-NEXT:    ret i8 [[TMP1]]
697   %s1 = sub nsw i8 %x, %y
698   %s2 = sub nuw i8 %y, %x
699   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
700   ret i8 %r
703 define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
704 ; CHECK-LABEL: @smax_negation_vec(
705 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
706 ; CHECK-NEXT:    ret <3 x i8> [[TMP1]]
708   %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
709   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
710   ret <3 x i8> %r
713 define i8 @smin_negation(i8 %x, i8 %y) {
714 ; CHECK-LABEL: @smin_negation(
715 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
716 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
717 ; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
718 ; CHECK-NEXT:    ret i8 [[NABS]]
720   %s1 = sub i8 %x, %y
721   %s2 = sub i8 %y, %x
722   %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)
723   ret i8 %r
726 define i8 @umax_negation(i8 %x, i8 %y) {
727 ; CHECK-LABEL: @umax_negation(
728 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
729 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
730 ; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
731 ; CHECK-NEXT:    ret i8 [[NABS]]
733   %s1 = sub nsw i8 %x, %y
734   %s2 = sub nsw i8 %y, %x
735   %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)
736   ret i8 %r
739 define i8 @umin_negation(i8 %x) {
740 ; CHECK-LABEL: @umin_negation(
741 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
742 ; CHECK-NEXT:    ret i8 [[TMP1]]
744   %s = sub nsw i8 0, %x
745   %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
746   ret i8 %r
749 define i8 @smax_negation_uses(i8 %x, i8 %y) {
750 ; CHECK-LABEL: @smax_negation_uses(
751 ; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
752 ; CHECK-NEXT:    call void @use(i8 [[S2]])
753 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false)
754 ; CHECK-NEXT:    ret i8 [[TMP1]]
756   %s1 = sub i8 %x, %y
757   %s2 = sub i8 %y, %x
758   call void @use(i8 %s2)
759   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
760   ret i8 %r
763 define i8 @clamp_two_vals_smax_smin(i8 %x) {
764 ; CHECK-LABEL: @clamp_two_vals_smax_smin(
765 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43
766 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
767 ; CHECK-NEXT:    ret i8 [[R]]
769   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
770   %r = call i8 @llvm.smin.i8(i8 %m, i8 43)
771   ret i8 %r
774 define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) {
775 ; CHECK-LABEL: @clamp_two_vals_smin_smax(
776 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 41, i8 41, i8 41>
777 ; CHECK-NEXT:    [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> <i8 42, i8 42, i8 42>, <3 x i8> <i8 41, i8 41, i8 41>
778 ; CHECK-NEXT:    ret <3 x i8> [[R]]
780   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)
781   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)
782   ret <3 x i8> %r
785 define i8 @clamp_two_vals_umax_umin(i8 %x) {
786 ; CHECK-LABEL: @clamp_two_vals_umax_umin(
787 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43
788 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
789 ; CHECK-NEXT:    ret i8 [[R]]
791   %m = call i8 @llvm.umax.i8(i8 %x, i8 42)
792   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
793   ret i8 %r
796 define i8 @clamp_two_vals_umin_umax(i8 %x) {
797 ; CHECK-LABEL: @clamp_two_vals_umin_umax(
798 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41
799 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41
800 ; CHECK-NEXT:    ret i8 [[R]]
802   %m = call i8 @llvm.umin.i8(i8 %x, i8 42)
803   %r = call i8 @llvm.umax.i8(i8 %m, i8 41)
804   ret i8 %r
807 ; Negative test - mismatched signs
809 define i8 @clamp_two_vals_smax_umin(i8 %x) {
810 ; CHECK-LABEL: @clamp_two_vals_smax_umin(
811 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
812 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43)
813 ; CHECK-NEXT:    ret i8 [[R]]
815   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
816   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
817   ret i8 %r
820 ; Negative test - wrong range
822 define i8 @clamp_three_vals_smax_smin(i8 %x) {
823 ; CHECK-LABEL: @clamp_three_vals_smax_smin(
824 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
825 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44)
826 ; CHECK-NEXT:    ret i8 [[R]]
828   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
829   %r = call i8 @llvm.smin.i8(i8 %m, i8 44)
830   ret i8 %r
833 ; Edge cases are simplified
835 define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
836 ; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
837 ; CHECK-NEXT:    ret i8 0
839   %m = call i8 @llvm.umax.i8(i8 %x, i8 255)
840   %r = call i8 @llvm.umin.i8(i8 %m, i8 0)
841   ret i8 %r
844 ; Edge cases are simplified
846 define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
847 ; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
848 ; CHECK-NEXT:    ret i8 -1
850   %m = call i8 @llvm.umin.i8(i8 %x, i8 0)
851   %r = call i8 @llvm.umax.i8(i8 %m, i8 255)
852   ret i8 %r
855 ; Edge cases are simplified
857 define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
858 ; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
859 ; CHECK-NEXT:    ret i8 -128
861   %m = call i8 @llvm.smax.i8(i8 %x, i8 127)
862   %r = call i8 @llvm.smin.i8(i8 %m, i8 128)
863   ret i8 %r
866 ; Edge cases are simplified
868 define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
869 ; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
870 ; CHECK-NEXT:    ret i8 127
872   %m = call i8 @llvm.smin.i8(i8 %x, i8 128)
873   %r = call i8 @llvm.smax.i8(i8 %m, i8 127)
874   ret i8 %r
878 define i8 @umin_non_zero_idiom1(i8 %a) {
879 ; CHECK-LABEL: @umin_non_zero_idiom1(
880 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
881 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
882 ; CHECK-NEXT:    ret i8 [[RES]]
884   %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
885   ret i8 %res
888 define i8 @umin_non_zero_idiom2(i8 %a) {
889 ; CHECK-LABEL: @umin_non_zero_idiom2(
890 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
891 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
892 ; CHECK-NEXT:    ret i8 [[RES]]
894   %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
895   ret i8 %res
898 define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
899 ; CHECK-LABEL: @umin_non_zero_idiom3(
900 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
901 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
902 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
904   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
905   ret <3 x i8> %res
908 define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
909 ; CHECK-LABEL: @umin_non_zero_idiom4(
910 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
911 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
912 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
914   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 undef, i8 undef>)
915   ret <3 x i8> %res
918 define i1 @umin_eq_zero(i8 %a, i8 %b) {
919 ; CHECK-LABEL: @umin_eq_zero(
920 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
921 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i8 [[UMIN]], 0
922 ; CHECK-NEXT:    ret i1 [[RES]]
924   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
925   %res = icmp eq i8 %umin, 0
926   ret i1 %res
929 define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) {
930 ; CHECK-LABEL: @umin_eq_zero2(
931 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
932 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer
933 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
936   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
937   %res = icmp eq <3 x i8> %umin, zeroinitializer
938   ret <3 x i1> %res
941 define i1 @umin_ne_zero(i8 %a, i8 %b) {
942 ; CHECK-LABEL: @umin_ne_zero(
943 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
944 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8 [[UMIN]], 0
945 ; CHECK-NEXT:    ret i1 [[RES]]
947   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
948   %res = icmp ne i8 %umin, 0
949   ret i1 %res
952 define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) {
953 ; CHECK-LABEL: @umin_ne_zero2(
954 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
955 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer
956 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
959   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
960   %res = icmp ne <3 x i8> %umin, zeroinitializer
961   ret <3 x i1> %res
964 define i8 @smax(i8 %x, i8 %y, i8 %z) {
965 ; CHECK-LABEL: @smax(
966 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]])
967 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]])
968 ; CHECK-NEXT:    ret i8 [[M3]]
970   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
971   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
972   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
973   ret i8 %m3
976 define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
977 ; CHECK-LABEL: @smin(
978 ; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]])
979 ; CHECK-NEXT:    [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]])
980 ; CHECK-NEXT:    ret <3 x i8> [[M3]]
982   %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)
983   %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)
984   %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)
985   ret <3 x i8> %m3
988 define i8 @umax(i8 %x, i8 %y, i8 %z) {
989 ; CHECK-LABEL: @umax(
990 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
991 ; CHECK-NEXT:    call void @use(i8 [[M1]])
992 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]])
993 ; CHECK-NEXT:    ret i8 [[M3]]
995   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
996   call void @use(i8 %m1)
997   %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)
998   %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)
999   ret i8 %m3
1002 define i8 @umin(i8 %x, i8 %y, i8 %z) {
1003 ; CHECK-LABEL: @umin(
1004 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]])
1005 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1006 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]])
1007 ; CHECK-NEXT:    ret i8 [[M3]]
1009   %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
1010   %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)
1011   call void @use(i8 %m2)
1012   %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)
1013   ret i8 %m3
1016 ; negative test - too many uses
1018 define i8 @smax_uses(i8 %x, i8 %y, i8 %z) {
1019 ; CHECK-LABEL: @smax_uses(
1020 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1021 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1022 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]])
1023 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1024 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1025 ; CHECK-NEXT:    ret i8 [[M3]]
1027   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1028   call void @use(i8 %m1)
1029   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
1030   call void @use(i8 %m2)
1031   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1032   ret i8 %m3
1035 ; negative test - must have common operand
1037 define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) {
1038 ; CHECK-LABEL: @smax_no_common_op(
1039 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1040 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]])
1041 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1042 ; CHECK-NEXT:    ret i8 [[M3]]
1044   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1045   %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)
1046   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1047   ret i8 %m3
1050 define i8 @umax_demand_lshr(i8 %x) {
1051 ; CHECK-LABEL: @umax_demand_lshr(
1052 ; CHECK-NEXT:    [[R:%.*]] = lshr i8 [[X:%.*]], 4
1053 ; CHECK-NEXT:    ret i8 [[R]]
1055   %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1056   %r = lshr i8 %m, 4
1057   ret i8 %r
1060 define i8 @umax_demand_and(i8 %x) {
1061 ; CHECK-LABEL: @umax_demand_and(
1062 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], 10
1063 ; CHECK-NEXT:    ret i8 [[R]]
1065   %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1066   %r = and i8 %m, 10
1067   ret i8 %r
1070 define i8 @umin_demand_or_31_30(i8 %x) {
1071 ; CHECK-LABEL: @umin_demand_or_31_30(
1072 ; CHECK-NEXT:    [[R:%.*]] = or i8 [[X:%.*]], 31
1073 ; CHECK-NEXT:    ret i8 [[R]]
1075   %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1076   %r = or i8 %m, 31
1077   ret i8 %r
1080 define i8 @umin_demand_and_7_8(i8 %x) {
1081 ; CHECK-LABEL: @umin_demand_and_7_8(
1082 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], -8
1083 ; CHECK-NEXT:    ret i8 [[R]]
1085   %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1086   %r = and i8 %m, -8
1087   ret i8 %r
1090 define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) {
1091 ; CHECK-LABEL: @neg_neg_nsw_smax(
1092 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1093 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1094 ; CHECK-NEXT:    ret i8 [[M]]
1096   %nx = sub nsw i8 0, %x
1097   %ny = sub nsw i8 0, %y
1098   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1099   ret i8 %m
1102 define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) {
1103 ; CHECK-LABEL: @neg_neg_nsw_smin(
1104 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
1105 ; CHECK-NEXT:    [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]]
1106 ; CHECK-NEXT:    ret <3 x i8> [[M]]
1108   %nx = sub nsw <3 x i8> zeroinitializer, %x
1109   %ny = sub nsw <3 x i8> zeroinitializer, %y
1110   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)
1111   ret <3 x i8> %m
1114 define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) {
1115 ; CHECK-LABEL: @neg_neg_nsw_smax_use0(
1116 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1117 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1118 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]])
1119 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1120 ; CHECK-NEXT:    ret i8 [[M]]
1122   %nx = sub nsw i8 0, %x
1123   call void @use(i8 %nx)
1124   %ny = sub nsw i8 0, %y
1125   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1126   ret i8 %m
1129 define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) {
1130 ; CHECK-LABEL: @neg_neg_nsw_smin_use1(
1131 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1132 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1133 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]])
1134 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1135 ; CHECK-NEXT:    ret i8 [[M]]
1137   %nx = sub nsw i8 0, %x
1138   %ny = sub nsw i8 0, %y
1139   call void @use(i8 %ny)
1140   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1141   ret i8 %m
1144 ; negative test - too many uses
1146 define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) {
1147 ; CHECK-LABEL: @neg_neg_nsw_smin_use2(
1148 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1149 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1150 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1151 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1152 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1153 ; CHECK-NEXT:    ret i8 [[M]]
1155   %nx = sub nsw i8 0, %x
1156   call void @use(i8 %nx)
1157   %ny = sub nsw i8 0, %y
1158   call void @use(i8 %ny)
1159   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1160   ret i8 %m
1163 ; negative test - need nsw on both ops
1165 define i8 @neg_neg_smax(i8 %x, i8 %y) {
1166 ; CHECK-LABEL: @neg_neg_smax(
1167 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1168 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1169 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]])
1170 ; CHECK-NEXT:    ret i8 [[M]]
1172   %nx = sub i8 0, %x
1173   %ny = sub nsw i8 0, %y
1174   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1175   ret i8 %m
1178 ; negative test - need nsw on both ops
1180 define i8 @neg_neg_smin(i8 %x, i8 %y) {
1181 ; CHECK-LABEL: @neg_neg_smin(
1182 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1183 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1184 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1185 ; CHECK-NEXT:    ret i8 [[M]]
1187   %nx = sub i8 0, %x
1188   %ny = sub nsw i8 0, %y
1189   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1190   ret i8 %m
1193 ; negative test - need signed min/max
1195 define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) {
1196 ; CHECK-LABEL: @neg_neg_nsw_umin(
1197 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1198 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1199 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
1200 ; CHECK-NEXT:    ret i8 [[M]]
1202   %nx = sub nsw i8 0, %x
1203   %ny = sub nsw i8 0, %y
1204   %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
1205   ret i8 %m
1208 define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {
1209 ; CHECK-LABEL: @freeToInvertSub(
1210 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1211 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1212 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1213 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1214 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1215 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1216 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1217 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[TMP1]], [[Z]]
1218 ; CHECK-NEXT:    ret i8 [[SUB]]
1220   %nx = xor i8 %x, -1
1221   %ny = xor i8 %y, -1
1222   %nz = xor i8 %z, -1
1223   call void @use(i8 %nx)
1224   call void @use(i8 %ny)
1225   call void @use(i8 %nz)
1226   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1227   %sub = sub i8 %nz, %m
1228   ret i8 %sub
1231 define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {
1232 ; CHECK-LABEL: @freeToInvertSub_uses(
1233 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1234 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1235 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1236 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1237 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1238 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1239 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1240 ; CHECK-NEXT:    call void @use(i8 [[M]])
1241 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1242 ; CHECK-NEXT:    ret i8 [[SUB]]
1244   %nx = xor i8 %x, -1
1245   %ny = xor i8 %y, -1
1246   %nz = xor i8 %z, -1
1247   call void @use(i8 %nx)
1248   call void @use(i8 %ny)
1249   call void @use(i8 %nz)
1250   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1251   call void @use(i8 %m)
1252   %sub = sub i8 %nz, %m
1253   ret i8 %sub
1256 define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {
1257 ; CHECK-LABEL: @freeToInvert(
1258 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1259 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1260 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1261 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1262 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1263 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1264 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1265 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[Z]])
1266 ; CHECK-NEXT:    ret i8 [[TMP2]]
1268   %nx = xor i8 %x, -1
1269   %ny = xor i8 %y, -1
1270   %nz = xor i8 %z, -1
1271   call void @use(i8 %nx)
1272   call void @use(i8 %ny)
1273   call void @use(i8 %nz)
1274   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1275   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1276   %not = xor i8 %m2, -1
1277   ret i8 %not
1280 define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {
1281 ; CHECK-LABEL: @freeToInvert_use1(
1282 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1283 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1284 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1285 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1286 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1287 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1288 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1289 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1290 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[M1]], -1
1291 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1292 ; CHECK-NEXT:    ret i8 [[TMP2]]
1294   %nx = xor i8 %x, -1
1295   %ny = xor i8 %y, -1
1296   %nz = xor i8 %z, -1
1297   call void @use(i8 %nx)
1298   call void @use(i8 %ny)
1299   call void @use(i8 %nz)
1300   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1301   call void @use(i8 %m1)
1302   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1303   %not = xor i8 %m2, -1
1304   ret i8 %not
1307 define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {
1308 ; CHECK-LABEL: @freeToInvert_use2(
1309 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1310 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1311 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1312 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1313 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1314 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1315 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1316 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1317 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1318 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1319 ; CHECK-NEXT:    ret i8 [[NOT]]
1321   %nx = xor i8 %x, -1
1322   %ny = xor i8 %y, -1
1323   %nz = xor i8 %z, -1
1324   call void @use(i8 %nx)
1325   call void @use(i8 %ny)
1326   call void @use(i8 %nz)
1327   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1328   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1329   call void @use(i8 %m2)
1330   %not = xor i8 %m2, -1
1331   ret i8 %not
1334 define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {
1335 ; CHECK-LABEL: @freeToInvert_use3(
1336 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1337 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1338 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1339 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1340 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1341 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1342 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1343 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1344 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1345 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1346 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1347 ; CHECK-NEXT:    ret i8 [[NOT]]
1349   %nx = xor i8 %x, -1
1350   %ny = xor i8 %y, -1
1351   %nz = xor i8 %z, -1
1352   call void @use(i8 %nx)
1353   call void @use(i8 %ny)
1354   call void @use(i8 %nz)
1355   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1356   call void @use(i8 %m1)
1357   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1358   call void @use(i8 %m2)
1359   %not = xor i8 %m2, -1
1360   ret i8 %not
1363 define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) {
1364 ; CHECK-LABEL: @freeToInvert_two_minmax_ops(
1365 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1366 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1367 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1368 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1369 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1370 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1371 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1372 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1373 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1374 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]])
1375 ; CHECK-NEXT:    [[TMP3:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]])
1376 ; CHECK-NEXT:    ret i8 [[TMP3]]
1378   %nx = xor i8 %x, -1
1379   %ny = xor i8 %y, -1
1380   %nz = xor i8 %z, -1
1381   %nw = xor i8 %w, -1
1382   call void @use(i8 %nx)
1383   call void @use(i8 %ny)
1384   call void @use(i8 %nz)
1385   call void @use(i8 %nw)
1386   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1387   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1388   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1389   %not = xor i8 %m3, -1
1390   ret i8 %not
1393 define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) {
1394 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1(
1395 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1396 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1397 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1398 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1399 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1400 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1401 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1402 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1403 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1404 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1405 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1406 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1407 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1408 ; CHECK-NEXT:    ret i8 [[NOT]]
1410   %nx = xor i8 %x, -1
1411   %ny = xor i8 %y, -1
1412   %nz = xor i8 %z, -1
1413   %nw = xor i8 %w, -1
1414   call void @use(i8 %nx)
1415   call void @use(i8 %ny)
1416   call void @use(i8 %nz)
1417   call void @use(i8 %nw)
1418   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1419   call void @use(i8 %m1)
1420   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1421   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1422   %not = xor i8 %m3, -1
1423   ret i8 %not
1426 define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) {
1427 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2(
1428 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1429 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1430 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1431 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1432 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1433 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1434 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1435 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1436 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1437 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1438 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1439 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1440 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1441 ; CHECK-NEXT:    ret i8 [[NOT]]
1443   %nx = xor i8 %x, -1
1444   %ny = xor i8 %y, -1
1445   %nz = xor i8 %z, -1
1446   %nw = xor i8 %w, -1
1447   call void @use(i8 %nx)
1448   call void @use(i8 %ny)
1449   call void @use(i8 %nz)
1450   call void @use(i8 %nw)
1451   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1452   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1453   call void @use(i8 %m2)
1454   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1455   %not = xor i8 %m3, -1
1456   ret i8 %not
1459 define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
1460 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3(
1461 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1462 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1463 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1464 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1465 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1466 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1467 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1468 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1469 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1470 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1471 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1472 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1473 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1474 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1475 ; CHECK-NEXT:    ret i8 [[NOT]]
1477   %nx = xor i8 %x, -1
1478   %ny = xor i8 %y, -1
1479   %nz = xor i8 %z, -1
1480   %nw = xor i8 %w, -1
1481   call void @use(i8 %nx)
1482   call void @use(i8 %ny)
1483   call void @use(i8 %nz)
1484   call void @use(i8 %nw)
1485   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1486   call void @use(i8 %m1)
1487   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1488   call void @use(i8 %m2)
1489   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1490   %not = xor i8 %m3, -1
1491   ret i8 %not
1494 define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) {
1495 ; CHECK-LABEL: @sub_not_min_max(
1496 ; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
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:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1502 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1503 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1504 ; CHECK-NEXT:    ret i8 [[CK]]
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
1517 define 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:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1526 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1527 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1528 ; CHECK-NEXT:    ret i8 [[CK]]
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
1542 define 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]]
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
1569 declare void @use4(i8, i8, i8, i8)
1571 define 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
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
1594 ; Same as above, but flip the operands of %k.
1596 define 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
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
1619 ; Same as above, but also flip the operands of %m.
1621 define 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
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
1644 ; Same as original, but only flip the operands of %m.
1646 define 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
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
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.
1672 define 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
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
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.
1698 define 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
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
1721 define 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
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
1744 ; Same as above, but flip the operands of %k.
1746 define 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
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
1769 ; Same as above, but also flip the operands of %m.
1771 define 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
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
1794 ; Same as original, but only flip the operands of %m.
1796 define 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
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
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.
1822 define 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
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
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.
1848 define 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
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
1871 define 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]]
1877   %a = add nsw i8 %x, 3
1878   %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1879   ret i8 %m
1882 ; This is handled by InstSimplify; testing here to confirm assert.
1884 define 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]]
1889   %a = add nsw i8 %x, 3
1890   %m = call i8 @llvm.smax.i8(i8 %a, i8 -125)
1891   ret i8 %m
1894 ; This is handled by InstSimplify; testing here to confirm assert.
1896 define 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]]
1901   %a = add nsw i8 %x, 3
1902   %m = call i8 @llvm.smax.i8(i8 %a, i8 -126)
1903   ret i8 %m
1906 ; negative test - require nsw
1908 define 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]]
1914   %a = add i8 %x, 3
1915   %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1916   ret i8 %m
1919 ; negative test
1921 define 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]]
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
1934 define <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> <i8 -127, i8 -127, i8 -127>)
1937 ; CHECK-NEXT:    [[M:%.*]] = or <3 x i8> [[TMP1]], <i8 124, i8 124, i8 124>
1938 ; CHECK-NEXT:    ret <3 x i8> [[M]]
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
1945 ; This is handled by InstSimplify; testing here to confirm assert.
1947 define i8 @smin_offset_limit(i8 %x) {
1948 ; CHECK-LABEL: @smin_offset_limit(
1949 ; CHECK-NEXT:    ret i8 -3
1951   %a = add nsw i8 %x, 125
1952   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1953   ret i8 %m
1956 ; This is handled by InstSimplify; testing here to confirm assert.
1958 define i8 @smin_offset_overflow(i8 %x) {
1959 ; CHECK-LABEL: @smin_offset_overflow(
1960 ; CHECK-NEXT:    ret i8 -3
1962   %a = add nsw i8 %x, 126
1963   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1964   ret i8 %m
1967 ; negative test - require nsw
1969 define 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]]
1975   %a = add nuw i8 %x, 124
1976   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1977   ret i8 %m
1980 ; negative test
1982 define 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]]
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
1995 ; Note: 'nsw' must not propagate here.
1997 define <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> <i8 3, i8 3, i8 3>)
2000 ; CHECK-NEXT:    [[M:%.*]] = add nuw <3 x i8> [[TMP1]], <i8 127, i8 127, i8 127>
2001 ; CHECK-NEXT:    ret <3 x i8> [[M]]
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
2008 ; This is handled by InstSimplify; testing here to confirm assert.
2010 define 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]]
2015   %a = add nuw i8 %x, 3
2016   %m = call i8 @llvm.umax.i8(i8 %a, i8 3)
2017   ret i8 %m
2020 ; This is handled by InstSimplify; testing here to confirm assert.
2022 define 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]]
2027   %a = add nuw i8 %x, 3
2028   %m = call i8 @llvm.umax.i8(i8 %a, i8 2)
2029   ret i8 %m
2032 ; negative test - require nuw
2034 define 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]]
2040   %a = add i8 %x, 3
2041   %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2042   ret i8 %m
2045 ; negative test
2047 define 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]]
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
2060 define 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]]
2066   %a = add nuw i8 %x, 251
2067   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2068   ret i8 %m
2071 ; This is handled by InstSimplify; testing here to confirm assert.
2073 define i8 @umin_offset_limit(i8 %x) {
2074 ; CHECK-LABEL: @umin_offset_limit(
2075 ; CHECK-NEXT:    ret i8 -4
2077   %a = add nuw i8 %x, 252
2078   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2079   ret i8 %m
2082 ; This is handled by InstSimplify; testing here to confirm assert.
2084 define i8 @umin_offset_overflow(i8 %x) {
2085 ; CHECK-LABEL: @umin_offset_overflow(
2086 ; CHECK-NEXT:    ret i8 -4
2088   %a = add nuw i8 %x, 253
2089   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2090   ret i8 %m
2093 ; negative test - require nuw
2095 define 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]]
2101   %a = add nsw i8 %x, 251
2102   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2103   ret i8 %m
2106 ; negative test
2108 define 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]]
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
2121 ; TODO: This could transform, but undef element must not propagate to the new add.
2123 define <3 x i8> @umax_vector_splat_undef(<3 x i8> %x) {
2124 ; CHECK-LABEL: @umax_vector_splat_undef(
2125 ; CHECK-NEXT:    [[A:%.*]] = add nuw <3 x i8> [[X:%.*]], <i8 undef, 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]]
2129   %a = add nuw <3 x i8> %x, <i8 undef, 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
2134 ; Issue #52884 - this would assert because of a failure to simplify.
2136 define 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]]
2141   %1 = add nuw nsw i8 50, %x
2142   %m = call i8 @llvm.smax.i8(i8 %1, i8 -124)
2143   ret i8 %m
2146 define <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]]
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
2156 define 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]]
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
2166 define <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]]
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
2176 ; extra use is ok
2178 define 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]]
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
2191 ; negative test - must have matching intrinsics
2193 define 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]]
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
2204 define 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]]
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
2215 define <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]]
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
2226 define 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]]
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
2237 define <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]]
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
2248 define 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]]
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
2261 define 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]]
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
2272 define <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]]
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
2283 define 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]]
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
2294 define <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]]
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
2305 define 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]]
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
2318 define 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]]
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
2330 define 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]]
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
2342 define 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]]
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
2354 define 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 (i8 (i8, i8)* @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]]
2360   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)
2361   %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 ptrtoint (i8 (i8, i8)* @umax_umax_reassoc_constantexpr_sink to i8))
2362   ret i8 %m2
2365 define <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]]
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
2377 define <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 undef, 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 undef, i32 0, i32 2>
2383 ; CHECK-NEXT:    ret <3 x i8> [[R]]
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
2392 define <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]]
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
2407 define <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]]
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
2419 ; negative test - must have 2 shuffles
2421 define <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]]
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
2432 ; negative test - must have identical masks
2434 define <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]]
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
2447 ; negative test - must be unary shuffles
2449 define <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]]
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
2462 ; negative test - too many uses
2464 define <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]]
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