Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / minmax-intrinsics.ll
blob0b7127f82b61251021155986eb8a2e254b829b95
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare i1 @llvm.umin.i1(i1, i1)
5 declare i8 @llvm.umin.i8(i8, i8)
6 declare i8 @llvm.umax.i8(i8, i8)
7 declare i8 @llvm.smin.i8(i8, i8)
8 declare i8 @llvm.smax.i8(i8, i8)
9 declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)
10 declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)
11 declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)
12 declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)
13 declare void @use(i8)
14 declare void @use_vec(<3 x i8>)
16 define i8 @umin_known_bits(i8 %x, i8 %y) {
17 ; CHECK-LABEL: @umin_known_bits(
18 ; CHECK-NEXT:    ret i8 0
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
26 define i8 @umax_known_bits(i8 %x, i8 %y) {
27 ; CHECK-LABEL: @umax_known_bits(
28 ; CHECK-NEXT:    ret i8 -128
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
36 define i8 @smin_known_bits(i8 %x, i8 %y) {
37 ; CHECK-LABEL: @smin_known_bits(
38 ; CHECK-NEXT:    ret i8 -128
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
46 define i8 @smax_known_bits(i8 %x, i8 %y) {
47 ; CHECK-LABEL: @smax_known_bits(
48 ; CHECK-NEXT:    ret i8 0
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
56 define 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]]
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
68 ; Extra use is ok.
70 define 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]]
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
85 ; Sext doesn't change unsigned min/max comparison of narrow values.
87 define 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]]
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
102 define <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]]
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
114 ; Negative test - zext may change sign of inputs
116 define 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]]
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
129 ; Negative test - zext may change sign of inputs
131 define 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]]
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
144 define 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]]
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
156 define 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]]
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
168 ; Negative test - mismatched types
170 define 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]]
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
183 ; Negative test - mismatched extends
185 define 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]]
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
198 ; Negative test - too many uses.
200 define 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]]
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
217 define 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]]
223   %e = sext i5 %x to i8
224   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
225   ret i8 %m
228 ; simplifies
230 define i8 @smax_sext_constant_big(i5 %x) {
231 ; CHECK-LABEL: @smax_sext_constant_big(
232 ; CHECK-NEXT:    ret i8 16
234   %e = sext i5 %x to i8
235   %m = call i8 @llvm.smax.i8(i8 %e, i8 16)
236   ret i8 %m
239 ; negative test
241 define 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]]
247   %e = zext i5 %x to i8
248   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
249   ret i8 %m
252 define <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]]
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
263 ; negative test
265 define 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]]
271   %e = zext i5 %x to i8
272   %m = call i8 @llvm.smin.i8(i8 %e, i8 7)
273   ret i8 %m
276 define 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]]
282   %e = sext i5 %x to i8
283   %m = call i8 @llvm.umax.i8(i8 %e, i8 7)
284   ret i8 %m
287 ; negative test
289 define 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]]
295   %e = sext i5 %x to i8
296   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
297   ret i8 %m
300 define <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]]
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
311 ; simplifies
313 define i8 @umax_zext_constant_big(i5 %x) {
314 ; CHECK-LABEL: @umax_zext_constant_big(
315 ; CHECK-NEXT:    ret i8 126
317   %e = zext i5 %x to i8
318   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
319   ret i8 %m
322 define 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]]
328   %e = sext i5 %x to i8
329   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
330   ret i8 %m
333 ; negative test
335 define 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]]
341   %e = sext i5 %x to i8
342   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
343   ret i8 %m
346 define 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]]
352   %e = zext i5 %x to i8
353   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
354   ret i8 %m
357 ; simplifies
359 define 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]]
364   %e = zext i5 %x to i8
365   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
366   ret i8 %m
369 ; negative test
371 define 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]]
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
384 define 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]]
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
396 ; Vectors are ok (including poison lanes of not ops)
398 define <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]]
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
410 ; An extra use is ok.
412 define 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]]
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
427 ; An extra use is ok.
429 define 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]]
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
444 ; Negative test - too many uses
446 define 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]]
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
463 ; Canonicalize 'not' after min/max.
465 define 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]]
471   %notx = xor i8 %x, -1
472   %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)
473   ret i8 %m
476 ; Vectors are ok (including poison lanes of not ops and min/max constant operand)
478 define <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]]
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
489 define 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]]
495   %notx = xor i8 %x, -1
496   %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)
497   ret i8 %m
500 define 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]]
506   %notx = xor i8 %x, -1
507   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
508   ret i8 %m
511 define 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]]
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
532 define 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]]
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
553 ; Negative test - don't infinite loop on constant expression
555 define 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]]
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
566 ; Negative test - too many uses
568 define 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]]
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
581 define 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]]
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
599 define 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]]
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
620 define 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]]
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
635 ; Negative test - this would require an extra instruction.
637 define 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]]
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
654 define 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]]
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
668 define 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]]
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
680 define 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]]
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
692 define 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]]
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
704 define <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]]
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
714 define 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]]
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
727 define 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]]
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
740 define 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]]
745   %s = sub nsw i8 0, %x
746   %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
747   ret i8 %r
750 define 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]]
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
764 define 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]]
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
775 define <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]]
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
786 define 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]]
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
797 define 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]]
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
808 ; Negative test - mismatched signs
810 define 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]]
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
821 ; Negative test - wrong range
823 define 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]]
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
834 ; Edge cases are simplified
836 define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
837 ; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
838 ; CHECK-NEXT:    ret i8 0
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
845 ; Edge cases are simplified
847 define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
848 ; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
849 ; CHECK-NEXT:    ret i8 -1
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
856 ; Edge cases are simplified
858 define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
859 ; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
860 ; CHECK-NEXT:    ret i8 -128
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
867 ; Edge cases are simplified
869 define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
870 ; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
871 ; CHECK-NEXT:    ret i8 127
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
879 define 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]]
885   %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
886   ret i8 %res
889 define 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]]
895   %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
896   ret i8 %res
899 define <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]]
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
909 define <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]]
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
919 define 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]]
925   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
926   %res = icmp eq i8 %umin, 0
927   ret i1 %res
930 define <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]]
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
942 define 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]]
948   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
949   %res = icmp ne i8 %umin, 0
950   ret i1 %res
953 define <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]]
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
965 define 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]]
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
977 define <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]]
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
989 define 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]]
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
1003 define 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]]
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
1017 ; negative test - too many uses
1019 define 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]]
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
1036 ; negative test - must have common operand
1038 define 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]]
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
1051 define 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]]
1056   %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1057   %r = lshr i8 %m, 4
1058   ret i8 %r
1061 define 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]]
1066   %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1067   %r = and i8 %m, 10
1068   ret i8 %r
1071 define 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]]
1076   %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1077   %r = or i8 %m, 31
1078   ret i8 %r
1081 define 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]]
1086   %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1087   %r = and i8 %m, -8
1088   ret i8 %r
1091 define 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]]
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
1103 define <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]]
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
1115 define 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]]
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
1130 define 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]]
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
1145 ; negative test - too many uses
1147 define 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]]
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
1164 ; negative test - need nsw on both ops
1166 define 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]]
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
1179 ; negative test - need nsw on both ops
1181 define 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]]
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
1194 ; negative test - need signed min/max
1196 define 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]]
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
1209 define 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]]
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
1232 define 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]]
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
1257 define 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]]
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
1281 define 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]]
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
1308 define 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]]
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
1335 define 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]]
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
1364 define 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]]
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
1394 define 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]]
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
1427 define 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]]
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
1460 define 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]]
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
1495 define 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]]
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:    [[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]]
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> splat (i8 -127))
1937 ; CHECK-NEXT:    [[M:%.*]] = or disjoint <3 x i8> [[TMP1]], splat (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> splat (i8 3))
2000 ; CHECK-NEXT:    [[M:%.*]] = add nuw <3 x i8> [[TMP1]], splat (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
2123 define <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]]
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
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 (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]]
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
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 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]]
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
2481 ; This would assert/crash because we tried to zext to i1.
2483 @g = external dso_local global i32, align 4
2485 define i1 @PR57986() {
2486 ; CHECK-LABEL: @PR57986(
2487 ; CHECK-NEXT:    ret i1 ptrtoint (ptr @g to i1)
2489   %umin = call i1 @llvm.umin.i1(i1 ptrtoint (ptr @g to i1), i1 true)
2490   ret i1 %umin
2493 define 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]]
2501 entry:
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
2509 define <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]]
2517 entry:
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
2525 define 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
2530 entry:
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
2538 define <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)
2543 entry:
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
2551 define 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]]
2560 entry:
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
2568 define 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]]
2577 entry:
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
2585 define 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]]
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
2597 define 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]]
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
2609 define 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]]
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
2621 define 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]]
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
2633 define 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]]
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
2646 define 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]]
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
2659 define 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]]
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