[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / minmax-intrinsics.ll
blob194a693e5580460e69ef7075de71beec6e832e58
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
4 declare i8 @llvm.umin.i8(i8, i8)
5 declare i8 @llvm.umax.i8(i8, i8)
6 declare i8 @llvm.smin.i8(i8, i8)
7 declare i8 @llvm.smax.i8(i8, i8)
8 declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)
9 declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)
10 declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)
11 declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)
12 declare void @use(i8)
14 define i8 @umin_known_bits(i8 %x, i8 %y) {
15 ; CHECK-LABEL: @umin_known_bits(
16 ; CHECK-NEXT:    ret i8 0
18   %x2 = and i8 %x, 127
19   %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y)
20   %r = and i8 %m, -128
21   ret i8 %r
24 define i8 @umax_known_bits(i8 %x, i8 %y) {
25 ; CHECK-LABEL: @umax_known_bits(
26 ; CHECK-NEXT:    ret i8 -128
28   %x2 = or i8 %x, -128
29   %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y)
30   %r = and i8 %m, -128
31   ret i8 %r
34 define i8 @smin_known_bits(i8 %x, i8 %y) {
35 ; CHECK-LABEL: @smin_known_bits(
36 ; CHECK-NEXT:    ret i8 -128
38   %x2 = or i8 %x, -128
39   %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y)
40   %r = and i8 %m, -128
41   ret i8 %r
44 define i8 @smax_known_bits(i8 %x, i8 %y) {
45 ; CHECK-LABEL: @smax_known_bits(
46 ; CHECK-NEXT:    ret i8 0
48   %x2 = and i8 %x, 127
49   %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y)
50   %r = and i8 %m, -128
51   ret i8 %r
54 define i8 @smax_sext(i5 %x, i5 %y) {
55 ; CHECK-LABEL: @smax_sext(
56 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
57 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
58 ; CHECK-NEXT:    ret i8 [[M]]
60   %sx = sext i5 %x to i8
61   %sy = sext i5 %y to i8
62   %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy)
63   ret i8 %m
66 ; Extra use is ok.
68 define i8 @smin_sext(i5 %x, i5 %y) {
69 ; CHECK-LABEL: @smin_sext(
70 ; CHECK-NEXT:    [[SY:%.*]] = sext i5 [[Y:%.*]] to i8
71 ; CHECK-NEXT:    call void @use(i8 [[SY]])
72 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Y]])
73 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
74 ; CHECK-NEXT:    ret i8 [[M]]
76   %sx = sext i5 %x to i8
77   %sy = sext i5 %y to i8
78   call void @use(i8 %sy)
79   %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy)
80   ret i8 %m
83 ; Sext doesn't change unsigned min/max comparison of narrow values.
85 define i8 @umax_sext(i5 %x, i5 %y) {
86 ; CHECK-LABEL: @umax_sext(
87 ; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
88 ; CHECK-NEXT:    call void @use(i8 [[SX]])
89 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X]], i5 [[Y:%.*]])
90 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
91 ; CHECK-NEXT:    ret i8 [[M]]
93   %sx = sext i5 %x to i8
94   call void @use(i8 %sx)
95   %sy = sext i5 %y to i8
96   %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy)
97   ret i8 %m
100 define <3 x i8> @umin_sext(<3 x i5> %x, <3 x i5> %y) {
101 ; CHECK-LABEL: @umin_sext(
102 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> [[Y:%.*]])
103 ; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
104 ; CHECK-NEXT:    ret <3 x i8> [[M]]
106   %sx = sext <3 x i5> %x to <3 x i8>
107   %sy = sext <3 x i5> %y to <3 x i8>
108   %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
109   ret <3 x i8> %m
112 ; Negative test - zext may change sign of inputs
114 define i8 @smax_zext(i5 %x, i5 %y) {
115 ; CHECK-LABEL: @smax_zext(
116 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
117 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
118 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]])
119 ; CHECK-NEXT:    ret i8 [[M]]
121   %zx = zext i5 %x to i8
122   %zy = zext i5 %y to i8
123   %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy)
124   ret i8 %m
127 ; Negative test - zext may change sign of inputs
129 define i8 @smin_zext(i5 %x, i5 %y) {
130 ; CHECK-LABEL: @smin_zext(
131 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
132 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
133 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]])
134 ; CHECK-NEXT:    ret i8 [[M]]
136   %zx = zext i5 %x to i8
137   %zy = zext i5 %y to i8
138   %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy)
139   ret i8 %m
142 define i8 @umax_zext(i5 %x, i5 %y) {
143 ; CHECK-LABEL: @umax_zext(
144 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
145 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
146 ; CHECK-NEXT:    ret i8 [[M]]
148   %zx = zext i5 %x to i8
149   %zy = zext i5 %y to i8
150   %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy)
151   ret i8 %m
154 define i8 @umin_zext(i5 %x, i5 %y) {
155 ; CHECK-LABEL: @umin_zext(
156 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
157 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
158 ; CHECK-NEXT:    ret i8 [[M]]
160   %zx = zext i5 %x to i8
161   %zy = zext i5 %y to i8
162   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
163   ret i8 %m
166 ; Negative test - mismatched types
168 define i8 @umin_zext_types(i6 %x, i5 %y) {
169 ; CHECK-LABEL: @umin_zext_types(
170 ; CHECK-NEXT:    [[ZX:%.*]] = zext i6 [[X:%.*]] to i8
171 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
172 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
173 ; CHECK-NEXT:    ret i8 [[M]]
175   %zx = zext i6 %x to i8
176   %zy = zext i5 %y to i8
177   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
178   ret i8 %m
181 ; Negative test - mismatched extends
183 define i8 @umin_ext(i5 %x, i5 %y) {
184 ; CHECK-LABEL: @umin_ext(
185 ; CHECK-NEXT:    [[SX:%.*]] = sext i5 [[X:%.*]] to i8
186 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
187 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]])
188 ; CHECK-NEXT:    ret i8 [[M]]
190   %sx = sext i5 %x to i8
191   %zy = zext i5 %y to i8
192   %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy)
193   ret i8 %m
196 ; Negative test - too many uses.
198 define i8 @umin_zext_uses(i5 %x, i5 %y) {
199 ; CHECK-LABEL: @umin_zext_uses(
200 ; CHECK-NEXT:    [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
201 ; CHECK-NEXT:    call void @use(i8 [[ZX]])
202 ; CHECK-NEXT:    [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
203 ; CHECK-NEXT:    call void @use(i8 [[ZY]])
204 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
205 ; CHECK-NEXT:    ret i8 [[M]]
207   %zx = zext i5 %x to i8
208   call void @use(i8 %zx)
209   %zy = zext i5 %y to i8
210   call void @use(i8 %zy)
211   %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
212   ret i8 %m
215 define i8 @smax_sext_constant(i5 %x) {
216 ; CHECK-LABEL: @smax_sext_constant(
217 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
218 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
219 ; CHECK-NEXT:    ret i8 [[M]]
221   %e = sext i5 %x to i8
222   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
223   ret i8 %m
226 ; simplifies
228 define i8 @smax_sext_constant_big(i5 %x) {
229 ; CHECK-LABEL: @smax_sext_constant_big(
230 ; CHECK-NEXT:    ret i8 16
232   %e = sext i5 %x to i8
233   %m = call i8 @llvm.smax.i8(i8 %e, i8 16)
234   ret i8 %m
237 ; negative test
239 define i8 @smax_zext_constant(i5 %x) {
240 ; CHECK-LABEL: @smax_zext_constant(
241 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
242 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
243 ; CHECK-NEXT:    ret i8 [[M]]
245   %e = zext i5 %x to i8
246   %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
247   ret i8 %m
250 define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
251 ; CHECK-LABEL: @smin_sext_constant(
252 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
253 ; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
254 ; CHECK-NEXT:    ret <3 x i8> [[M]]
256   %e = sext <3 x i5> %x to <3 x i8>
257   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>)
258   ret <3 x i8> %m
261 ; negative test
263 define i8 @smin_zext_constant(i5 %x) {
264 ; CHECK-LABEL: @smin_zext_constant(
265 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
266 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7)
267 ; CHECK-NEXT:    ret i8 [[M]]
269   %e = zext i5 %x to i8
270   %m = call i8 @llvm.smin.i8(i8 %e, i8 7)
271   ret i8 %m
274 define i8 @umax_sext_constant(i5 %x) {
275 ; CHECK-LABEL: @umax_sext_constant(
276 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
277 ; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
278 ; CHECK-NEXT:    ret i8 [[M]]
280   %e = sext i5 %x to i8
281   %m = call i8 @llvm.umax.i8(i8 %e, i8 7)
282   ret i8 %m
285 ; negative test
287 define i8 @umax_sext_constant_big(i5 %x) {
288 ; CHECK-LABEL: @umax_sext_constant_big(
289 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
290 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126)
291 ; CHECK-NEXT:    ret i8 [[M]]
293   %e = sext i5 %x to i8
294   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
295   ret i8 %m
298 define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
299 ; CHECK-LABEL: @umax_zext_constant(
300 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
301 ; CHECK-NEXT:    [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
302 ; CHECK-NEXT:    ret <3 x i8> [[M]]
304   %e = zext <3 x i5> %x to <3 x i8>
305   %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>)
306   ret <3 x i8> %m
309 ; simplifies
311 define i8 @umax_zext_constant_big(i5 %x) {
312 ; CHECK-LABEL: @umax_zext_constant_big(
313 ; CHECK-NEXT:    ret i8 126
315   %e = zext i5 %x to i8
316   %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
317   ret i8 %m
320 define i8 @umin_sext_constant(i5 %x) {
321 ; CHECK-LABEL: @umin_sext_constant(
322 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
323 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
324 ; CHECK-NEXT:    ret i8 [[M]]
326   %e = sext i5 %x to i8
327   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
328   ret i8 %m
331 ; negative test
333 define i8 @umin_sext_constant_big(i5 %x) {
334 ; CHECK-LABEL: @umin_sext_constant_big(
335 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
336 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126)
337 ; CHECK-NEXT:    ret i8 [[M]]
339   %e = sext i5 %x to i8
340   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
341   ret i8 %m
344 define i8 @umin_zext_constant(i5 %x) {
345 ; CHECK-LABEL: @umin_zext_constant(
346 ; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
347 ; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
348 ; CHECK-NEXT:    ret i8 [[M]]
350   %e = zext i5 %x to i8
351   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
352   ret i8 %m
355 ; simplifies
357 define i8 @umin_zext_constant_big(i5 %x) {
358 ; CHECK-LABEL: @umin_zext_constant_big(
359 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
360 ; CHECK-NEXT:    ret i8 [[E]]
362   %e = zext i5 %x to i8
363   %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
364   ret i8 %m
367 ; negative test
369 define i8 @umin_zext_constant_uses(i5 %x) {
370 ; CHECK-LABEL: @umin_zext_constant_uses(
371 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
372 ; CHECK-NEXT:    call void @use(i8 [[E]])
373 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
374 ; CHECK-NEXT:    ret i8 [[M]]
376   %e = zext i5 %x to i8
377   call void @use(i8 %e)
378   %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
379   ret i8 %m
382 define i8 @smax_of_nots(i8 %x, i8 %y) {
383 ; CHECK-LABEL: @smax_of_nots(
384 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
385 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
386 ; CHECK-NEXT:    ret i8 [[M]]
388   %notx = xor i8 %x, -1
389   %noty = xor i8 %y, -1
390   %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
391   ret i8 %m
394 ; Vectors are ok (including undef lanes of not ops)
396 define <3 x i8> @smin_of_nots(<3 x i8> %x, <3 x i8> %y) {
397 ; CHECK-LABEL: @smin_of_nots(
398 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
399 ; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1>
400 ; CHECK-NEXT:    ret <3 x i8> [[M]]
402   %notx = xor <3 x i8> %x, <i8 -1, i8 undef, i8 -1>
403   %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 undef>
404   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty)
405   ret <3 x i8> %m
408 ; An extra use is ok.
410 define i8 @umax_of_nots(i8 %x, i8 %y) {
411 ; CHECK-LABEL: @umax_of_nots(
412 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
413 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
414 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]])
415 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
416 ; CHECK-NEXT:    ret i8 [[M]]
418   %notx = xor i8 %x, -1
419   call void @use(i8 %notx)
420   %noty = xor i8 %y, -1
421   %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty)
422   ret i8 %m
425 ; An extra use is ok.
427 define i8 @umin_of_nots(i8 %x, i8 %y) {
428 ; CHECK-LABEL: @umin_of_nots(
429 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
430 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
431 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y]])
432 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
433 ; CHECK-NEXT:    ret i8 [[M]]
435   %notx = xor i8 %x, -1
436   %noty = xor i8 %y, -1
437   call void @use(i8 %noty)
438   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
439   ret i8 %m
442 ; Negative test - too many uses
444 define i8 @umin_of_nots_uses(i8 %x, i8 %y) {
445 ; CHECK-LABEL: @umin_of_nots_uses(
446 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
447 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
448 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
449 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
450 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[NOTY]])
451 ; CHECK-NEXT:    ret i8 [[M]]
453   %notx = xor i8 %x, -1
454   call void @use(i8 %notx)
455   %noty = xor i8 %y, -1
456   call void @use(i8 %noty)
457   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
458   ret i8 %m
461 ; Canonicalize 'not' after min/max.
463 define i8 @smax_of_not_and_const(i8 %x) {
464 ; CHECK-LABEL: @smax_of_not_and_const(
465 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -43)
466 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
467 ; CHECK-NEXT:    ret i8 [[M]]
469   %notx = xor i8 %x, -1
470   %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)
471   ret i8 %m
474 ; Vectors are ok (including undef lanes of not ops and min/max constant operand)
476 define <3 x i8> @smin_of_not_and_const(<3 x i8> %x) {
477 ; CHECK-LABEL: @smin_of_not_and_const(
478 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -43, i8 undef, i8 -44>)
479 ; CHECK-NEXT:    [[M:%.*]] = xor <3 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1>
480 ; CHECK-NEXT:    ret <3 x i8> [[M]]
482   %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 undef>
483   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 undef, i8 43>, <3 x i8> %notx)
484   ret <3 x i8> %m
487 define i8 @umax_of_not_and_const(i8 %x) {
488 ; CHECK-LABEL: @umax_of_not_and_const(
489 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -45)
490 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
491 ; CHECK-NEXT:    ret i8 [[M]]
493   %notx = xor i8 %x, -1
494   %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)
495   ret i8 %m
498 define i8 @umin_of_not_and_const(i8 %x) {
499 ; CHECK-LABEL: @umin_of_not_and_const(
500 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 44)
501 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
502 ; CHECK-NEXT:    ret i8 [[M]]
504   %notx = xor i8 %x, -1
505   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
506   ret i8 %m
509 define i8 @umin_of_not_and_smax(i8 %x, i8 %y, i8 %z) {
510 ; CHECK-LABEL: @umin_of_not_and_smax(
511 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
512 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
513 ; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
514 ; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
515 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[Z]])
516 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[TMP1]])
517 ; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
518 ; CHECK-NEXT:    ret i8 [[M2]]
520   %notx = xor i8 %x, -1
521   %noty = xor i8 %y, -1
522   call void @use(i8 %noty)
523   %notz = xor i8 %z, -1
524   call void @use(i8 %notz)
525   %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz)
526   %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx)
527   ret i8 %m2
530 define i8 @smin_of_umax_and_not(i8 %x, i8 %y, i8 %z) {
531 ; CHECK-LABEL: @smin_of_umax_and_not(
532 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
533 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
534 ; CHECK-NEXT:    [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
535 ; CHECK-NEXT:    call void @use(i8 [[NOTZ]])
536 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
537 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[TMP1]])
538 ; CHECK-NEXT:    [[M2:%.*]] = xor i8 [[TMP2]], -1
539 ; CHECK-NEXT:    ret i8 [[M2]]
541   %notx = xor i8 %x, -1
542   %noty = xor i8 %y, -1
543   call void @use(i8 %noty)
544   %notz = xor i8 %z, -1
545   call void @use(i8 %notz)
546   %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz)
547   %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1)
548   ret i8 %m2
551 ; Negative test - don't infinite loop on constant expression
553 define i8 @umin_of_not_and_nontrivial_const(i8 %x) {
554 ; CHECK-LABEL: @umin_of_not_and_nontrivial_const(
555 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
556 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (i8 (i8)* @umin_of_not_and_nontrivial_const to i8))
557 ; CHECK-NEXT:    ret i8 [[M]]
559   %notx = xor i8 %x, -1
560   %m = call i8 @llvm.umin.i8(i8 ptrtoint (i8(i8)* @umin_of_not_and_nontrivial_const to i8), i8 %notx)
561   ret i8 %m
564 ; Negative test - too many uses
566 define i8 @umin_of_not_and_const_uses(i8 %x) {
567 ; CHECK-LABEL: @umin_of_not_and_const_uses(
568 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
569 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
570 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45)
571 ; CHECK-NEXT:    ret i8 [[M]]
573   %notx = xor i8 %x, -1
574   call void @use(i8 %notx)
575   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
576   ret i8 %m
579 define i8 @not_smax_of_nots(i8 %x, i8 %y) {
580 ; CHECK-LABEL: @not_smax_of_nots(
581 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
582 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
583 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
584 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
585 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
586 ; CHECK-NEXT:    ret i8 [[TMP1]]
588   %notx = xor i8 %x, -1
589   call void @use(i8 %notx)
590   %noty = xor i8 %y, -1
591   call void @use(i8 %noty)
592   %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
593   %notm = xor i8 %m, -1
594   ret i8 %notm
597 define i8 @not_smin_of_nots(i8 %x, i8 %y) {
598 ; CHECK-LABEL: @not_smin_of_nots(
599 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
600 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
601 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
602 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
603 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]])
604 ; CHECK-NEXT:    call void @use(i8 [[M]])
605 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
606 ; CHECK-NEXT:    ret i8 [[NOTM]]
608   %notx = xor i8 %x, -1
609   call void @use(i8 %notx)
610   %noty = xor i8 %y, -1
611   call void @use(i8 %noty)
612   %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty)
613   call void @use(i8 %m)
614   %notm = xor i8 %m, -1
615   ret i8 %notm
618 define i8 @not_umax_of_not(i8 %x, i8 %y) {
619 ; CHECK-LABEL: @not_umax_of_not(
620 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
621 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
622 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
623 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])
624 ; CHECK-NEXT:    ret i8 [[TMP2]]
626   %notx = xor i8 %x, -1
627   call void @use(i8 %notx)
628   %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)
629   %notm = xor i8 %m, -1
630   ret i8 %notm
633 ; Negative test - this would require an extra instruction.
635 define i8 @not_umin_of_not(i8 %x, i8 %y) {
636 ; CHECK-LABEL: @not_umin_of_not(
637 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
638 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
639 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]])
640 ; CHECK-NEXT:    call void @use(i8 [[M]])
641 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
642 ; CHECK-NEXT:    ret i8 [[NOTM]]
644   %notx = xor i8 %x, -1
645   call void @use(i8 %notx)
646   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y)
647   call void @use(i8 %m)
648   %notm = xor i8 %m, -1
649   ret i8 %notm
652 define i8 @not_umin_of_not_constant_op(i8 %x) {
653 ; CHECK-LABEL: @not_umin_of_not_constant_op(
654 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
655 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
656 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43)
657 ; CHECK-NEXT:    ret i8 [[TMP1]]
659   %notx = xor i8 %x, -1
660   call void @use(i8 %notx)
661   %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)
662   %notm = xor i8 %m, -1
663   ret i8 %notm
666 define i8 @smax_negation(i8 %x, i8 %y) {
667 ; CHECK-LABEL: @smax_negation(
668 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
669 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
670 ; CHECK-NEXT:    ret i8 [[TMP1]]
672   %s1 = sub i8 %x, %y
673   %s2 = sub i8 %y, %x
674   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
675   ret i8 %r
678 define i8 @smax_negation_nsw(i8 %x, i8 %y) {
679 ; CHECK-LABEL: @smax_negation_nsw(
680 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
681 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
682 ; CHECK-NEXT:    ret i8 [[TMP1]]
684   %s1 = sub nsw i8 %x, %y
685   %s2 = sub nsw i8 %y, %x
686   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
687   ret i8 %r
690 define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
691 ; CHECK-LABEL: @smax_negation_not_nsw(
692 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
693 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
694 ; CHECK-NEXT:    ret i8 [[TMP1]]
696   %s1 = sub nsw i8 %x, %y
697   %s2 = sub nuw i8 %y, %x
698   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
699   ret i8 %r
702 define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
703 ; CHECK-LABEL: @smax_negation_vec(
704 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
705 ; CHECK-NEXT:    ret <3 x i8> [[TMP1]]
707   %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
708   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
709   ret <3 x i8> %r
712 define i8 @smin_negation(i8 %x, i8 %y) {
713 ; CHECK-LABEL: @smin_negation(
714 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
715 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
716 ; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
717 ; CHECK-NEXT:    ret i8 [[NABS]]
719   %s1 = sub i8 %x, %y
720   %s2 = sub i8 %y, %x
721   %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)
722   ret i8 %r
725 define i8 @umax_negation(i8 %x, i8 %y) {
726 ; CHECK-LABEL: @umax_negation(
727 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
728 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
729 ; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
730 ; CHECK-NEXT:    ret i8 [[NABS]]
732   %s1 = sub nsw i8 %x, %y
733   %s2 = sub nsw i8 %y, %x
734   %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)
735   ret i8 %r
738 define i8 @umin_negation(i8 %x) {
739 ; CHECK-LABEL: @umin_negation(
740 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
741 ; CHECK-NEXT:    ret i8 [[TMP1]]
743   %s = sub nsw i8 0, %x
744   %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
745   ret i8 %r
748 define i8 @smax_negation_uses(i8 %x, i8 %y) {
749 ; CHECK-LABEL: @smax_negation_uses(
750 ; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
751 ; CHECK-NEXT:    call void @use(i8 [[S2]])
752 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false)
753 ; CHECK-NEXT:    ret i8 [[TMP1]]
755   %s1 = sub i8 %x, %y
756   %s2 = sub i8 %y, %x
757   call void @use(i8 %s2)
758   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
759   ret i8 %r
762 define i8 @clamp_two_vals_smax_smin(i8 %x) {
763 ; CHECK-LABEL: @clamp_two_vals_smax_smin(
764 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43
765 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
766 ; CHECK-NEXT:    ret i8 [[R]]
768   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
769   %r = call i8 @llvm.smin.i8(i8 %m, i8 43)
770   ret i8 %r
773 define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) {
774 ; CHECK-LABEL: @clamp_two_vals_smin_smax(
775 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 41, i8 41, i8 41>
776 ; CHECK-NEXT:    [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> <i8 42, i8 42, i8 42>, <3 x i8> <i8 41, i8 41, i8 41>
777 ; CHECK-NEXT:    ret <3 x i8> [[R]]
779   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)
780   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)
781   ret <3 x i8> %r
784 define i8 @clamp_two_vals_umax_umin(i8 %x) {
785 ; CHECK-LABEL: @clamp_two_vals_umax_umin(
786 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43
787 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
788 ; CHECK-NEXT:    ret i8 [[R]]
790   %m = call i8 @llvm.umax.i8(i8 %x, i8 42)
791   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
792   ret i8 %r
795 define i8 @clamp_two_vals_umin_umax(i8 %x) {
796 ; CHECK-LABEL: @clamp_two_vals_umin_umax(
797 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41
798 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41
799 ; CHECK-NEXT:    ret i8 [[R]]
801   %m = call i8 @llvm.umin.i8(i8 %x, i8 42)
802   %r = call i8 @llvm.umax.i8(i8 %m, i8 41)
803   ret i8 %r
806 ; Negative test - mismatched signs
808 define i8 @clamp_two_vals_smax_umin(i8 %x) {
809 ; CHECK-LABEL: @clamp_two_vals_smax_umin(
810 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
811 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43)
812 ; CHECK-NEXT:    ret i8 [[R]]
814   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
815   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
816   ret i8 %r
819 ; Negative test - wrong range
821 define i8 @clamp_three_vals_smax_smin(i8 %x) {
822 ; CHECK-LABEL: @clamp_three_vals_smax_smin(
823 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
824 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44)
825 ; CHECK-NEXT:    ret i8 [[R]]
827   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
828   %r = call i8 @llvm.smin.i8(i8 %m, i8 44)
829   ret i8 %r
832 ; Edge cases are simplified
834 define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
835 ; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
836 ; CHECK-NEXT:    ret i8 0
838   %m = call i8 @llvm.umax.i8(i8 %x, i8 255)
839   %r = call i8 @llvm.umin.i8(i8 %m, i8 0)
840   ret i8 %r
843 ; Edge cases are simplified
845 define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
846 ; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
847 ; CHECK-NEXT:    ret i8 -1
849   %m = call i8 @llvm.umin.i8(i8 %x, i8 0)
850   %r = call i8 @llvm.umax.i8(i8 %m, i8 255)
851   ret i8 %r
854 ; Edge cases are simplified
856 define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
857 ; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
858 ; CHECK-NEXT:    ret i8 -128
860   %m = call i8 @llvm.smax.i8(i8 %x, i8 127)
861   %r = call i8 @llvm.smin.i8(i8 %m, i8 128)
862   ret i8 %r
865 ; Edge cases are simplified
867 define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
868 ; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
869 ; CHECK-NEXT:    ret i8 127
871   %m = call i8 @llvm.smin.i8(i8 %x, i8 128)
872   %r = call i8 @llvm.smax.i8(i8 %m, i8 127)
873   ret i8 %r
877 define i8 @umin_non_zero_idiom1(i8 %a) {
878 ; CHECK-LABEL: @umin_non_zero_idiom1(
879 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
880 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
881 ; CHECK-NEXT:    ret i8 [[RES]]
883   %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
884   ret i8 %res
887 define i8 @umin_non_zero_idiom2(i8 %a) {
888 ; CHECK-LABEL: @umin_non_zero_idiom2(
889 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
890 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
891 ; CHECK-NEXT:    ret i8 [[RES]]
893   %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
894   ret i8 %res
897 define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
898 ; CHECK-LABEL: @umin_non_zero_idiom3(
899 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
900 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
901 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
903   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
904   ret <3 x i8> %res
907 define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
908 ; CHECK-LABEL: @umin_non_zero_idiom4(
909 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
910 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
911 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
913   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 undef, i8 undef>)
914   ret <3 x i8> %res
917 define i1 @umin_eq_zero(i8 %a, i8 %b) {
918 ; CHECK-LABEL: @umin_eq_zero(
919 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
920 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i8 [[UMIN]], 0
921 ; CHECK-NEXT:    ret i1 [[RES]]
923   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
924   %res = icmp eq i8 %umin, 0
925   ret i1 %res
928 define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) {
929 ; CHECK-LABEL: @umin_eq_zero2(
930 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
931 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer
932 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
935   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
936   %res = icmp eq <3 x i8> %umin, zeroinitializer
937   ret <3 x i1> %res
940 define i1 @umin_ne_zero(i8 %a, i8 %b) {
941 ; CHECK-LABEL: @umin_ne_zero(
942 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
943 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8 [[UMIN]], 0
944 ; CHECK-NEXT:    ret i1 [[RES]]
946   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
947   %res = icmp ne i8 %umin, 0
948   ret i1 %res
951 define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) {
952 ; CHECK-LABEL: @umin_ne_zero2(
953 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
954 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer
955 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
958   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
959   %res = icmp ne <3 x i8> %umin, zeroinitializer
960   ret <3 x i1> %res
963 define i8 @smax(i8 %x, i8 %y, i8 %z) {
964 ; CHECK-LABEL: @smax(
965 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]])
966 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]])
967 ; CHECK-NEXT:    ret i8 [[M3]]
969   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
970   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
971   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
972   ret i8 %m3
975 define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
976 ; CHECK-LABEL: @smin(
977 ; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]])
978 ; CHECK-NEXT:    [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]])
979 ; CHECK-NEXT:    ret <3 x i8> [[M3]]
981   %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)
982   %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)
983   %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)
984   ret <3 x i8> %m3
987 define i8 @umax(i8 %x, i8 %y, i8 %z) {
988 ; CHECK-LABEL: @umax(
989 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
990 ; CHECK-NEXT:    call void @use(i8 [[M1]])
991 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]])
992 ; CHECK-NEXT:    ret i8 [[M3]]
994   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
995   call void @use(i8 %m1)
996   %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)
997   %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)
998   ret i8 %m3
1001 define i8 @umin(i8 %x, i8 %y, i8 %z) {
1002 ; CHECK-LABEL: @umin(
1003 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]])
1004 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1005 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]])
1006 ; CHECK-NEXT:    ret i8 [[M3]]
1008   %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
1009   %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)
1010   call void @use(i8 %m2)
1011   %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)
1012   ret i8 %m3
1015 ; negative test - too many uses
1017 define i8 @smax_uses(i8 %x, i8 %y, i8 %z) {
1018 ; CHECK-LABEL: @smax_uses(
1019 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1020 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1021 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]])
1022 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1023 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1024 ; CHECK-NEXT:    ret i8 [[M3]]
1026   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1027   call void @use(i8 %m1)
1028   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
1029   call void @use(i8 %m2)
1030   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1031   ret i8 %m3
1034 ; negative test - must have common operand
1036 define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) {
1037 ; CHECK-LABEL: @smax_no_common_op(
1038 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1039 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]])
1040 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1041 ; CHECK-NEXT:    ret i8 [[M3]]
1043   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1044   %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)
1045   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1046   ret i8 %m3
1049 define i8 @umax_demand_lshr(i8 %x) {
1050 ; CHECK-LABEL: @umax_demand_lshr(
1051 ; CHECK-NEXT:    [[R:%.*]] = lshr i8 [[X:%.*]], 4
1052 ; CHECK-NEXT:    ret i8 [[R]]
1054   %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1055   %r = lshr i8 %m, 4
1056   ret i8 %r
1059 define i8 @umax_demand_and(i8 %x) {
1060 ; CHECK-LABEL: @umax_demand_and(
1061 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], 10
1062 ; CHECK-NEXT:    ret i8 [[R]]
1064   %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1065   %r = and i8 %m, 10
1066   ret i8 %r
1069 define i8 @umin_demand_or_31_30(i8 %x) {
1070 ; CHECK-LABEL: @umin_demand_or_31_30(
1071 ; CHECK-NEXT:    [[R:%.*]] = or i8 [[X:%.*]], 31
1072 ; CHECK-NEXT:    ret i8 [[R]]
1074   %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1075   %r = or i8 %m, 31
1076   ret i8 %r
1079 define i8 @umin_demand_and_7_8(i8 %x) {
1080 ; CHECK-LABEL: @umin_demand_and_7_8(
1081 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], -8
1082 ; CHECK-NEXT:    ret i8 [[R]]
1084   %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1085   %r = and i8 %m, -8
1086   ret i8 %r
1089 define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) {
1090 ; CHECK-LABEL: @neg_neg_nsw_smax(
1091 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1092 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1093 ; CHECK-NEXT:    ret i8 [[M]]
1095   %nx = sub nsw i8 0, %x
1096   %ny = sub nsw i8 0, %y
1097   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1098   ret i8 %m
1101 define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) {
1102 ; CHECK-LABEL: @neg_neg_nsw_smin(
1103 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
1104 ; CHECK-NEXT:    [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]]
1105 ; CHECK-NEXT:    ret <3 x i8> [[M]]
1107   %nx = sub nsw <3 x i8> zeroinitializer, %x
1108   %ny = sub nsw <3 x i8> zeroinitializer, %y
1109   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)
1110   ret <3 x i8> %m
1113 define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) {
1114 ; CHECK-LABEL: @neg_neg_nsw_smax_use0(
1115 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1116 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1117 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]])
1118 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1119 ; CHECK-NEXT:    ret i8 [[M]]
1121   %nx = sub nsw i8 0, %x
1122   call void @use(i8 %nx)
1123   %ny = sub nsw i8 0, %y
1124   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1125   ret i8 %m
1128 define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) {
1129 ; CHECK-LABEL: @neg_neg_nsw_smin_use1(
1130 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1131 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1132 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]])
1133 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1134 ; CHECK-NEXT:    ret i8 [[M]]
1136   %nx = sub nsw i8 0, %x
1137   %ny = sub nsw i8 0, %y
1138   call void @use(i8 %ny)
1139   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1140   ret i8 %m
1143 ; negative test - too many uses
1145 define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) {
1146 ; CHECK-LABEL: @neg_neg_nsw_smin_use2(
1147 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1148 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1149 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1150 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1151 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1152 ; CHECK-NEXT:    ret i8 [[M]]
1154   %nx = sub nsw i8 0, %x
1155   call void @use(i8 %nx)
1156   %ny = sub nsw i8 0, %y
1157   call void @use(i8 %ny)
1158   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1159   ret i8 %m
1162 ; negative test - need nsw on both ops
1164 define i8 @neg_neg_smax(i8 %x, i8 %y) {
1165 ; CHECK-LABEL: @neg_neg_smax(
1166 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1167 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1168 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]])
1169 ; CHECK-NEXT:    ret i8 [[M]]
1171   %nx = sub i8 0, %x
1172   %ny = sub nsw i8 0, %y
1173   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1174   ret i8 %m
1177 ; negative test - need nsw on both ops
1179 define i8 @neg_neg_smin(i8 %x, i8 %y) {
1180 ; CHECK-LABEL: @neg_neg_smin(
1181 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1182 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1183 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1184 ; CHECK-NEXT:    ret i8 [[M]]
1186   %nx = sub i8 0, %x
1187   %ny = sub nsw i8 0, %y
1188   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1189   ret i8 %m
1192 ; negative test - need signed min/max
1194 define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) {
1195 ; CHECK-LABEL: @neg_neg_nsw_umin(
1196 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1197 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1198 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
1199 ; CHECK-NEXT:    ret i8 [[M]]
1201   %nx = sub nsw i8 0, %x
1202   %ny = sub nsw i8 0, %y
1203   %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
1204   ret i8 %m
1207 define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {
1208 ; CHECK-LABEL: @freeToInvertSub(
1209 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1210 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1211 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1212 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1213 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1214 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1215 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1216 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[TMP1]], [[Z]]
1217 ; CHECK-NEXT:    ret i8 [[SUB]]
1219   %nx = xor i8 %x, -1
1220   %ny = xor i8 %y, -1
1221   %nz = xor i8 %z, -1
1222   call void @use(i8 %nx)
1223   call void @use(i8 %ny)
1224   call void @use(i8 %nz)
1225   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1226   %sub = sub i8 %nz, %m
1227   ret i8 %sub
1230 define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {
1231 ; CHECK-LABEL: @freeToInvertSub_uses(
1232 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1233 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1234 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1235 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1236 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1237 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1238 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1239 ; CHECK-NEXT:    call void @use(i8 [[M]])
1240 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1241 ; CHECK-NEXT:    ret i8 [[SUB]]
1243   %nx = xor i8 %x, -1
1244   %ny = xor i8 %y, -1
1245   %nz = xor i8 %z, -1
1246   call void @use(i8 %nx)
1247   call void @use(i8 %ny)
1248   call void @use(i8 %nz)
1249   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1250   call void @use(i8 %m)
1251   %sub = sub i8 %nz, %m
1252   ret i8 %sub
1255 define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {
1256 ; CHECK-LABEL: @freeToInvert(
1257 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1258 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1259 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1260 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1261 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1262 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1263 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1264 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[Z]])
1265 ; CHECK-NEXT:    ret i8 [[TMP2]]
1267   %nx = xor i8 %x, -1
1268   %ny = xor i8 %y, -1
1269   %nz = xor i8 %z, -1
1270   call void @use(i8 %nx)
1271   call void @use(i8 %ny)
1272   call void @use(i8 %nz)
1273   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1274   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1275   %not = xor i8 %m2, -1
1276   ret i8 %not
1279 define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {
1280 ; CHECK-LABEL: @freeToInvert_use1(
1281 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1282 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1283 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1284 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1285 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1286 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1287 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1288 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1289 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[M1]], -1
1290 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1291 ; CHECK-NEXT:    ret i8 [[TMP2]]
1293   %nx = xor i8 %x, -1
1294   %ny = xor i8 %y, -1
1295   %nz = xor i8 %z, -1
1296   call void @use(i8 %nx)
1297   call void @use(i8 %ny)
1298   call void @use(i8 %nz)
1299   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1300   call void @use(i8 %m1)
1301   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1302   %not = xor i8 %m2, -1
1303   ret i8 %not
1306 define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {
1307 ; CHECK-LABEL: @freeToInvert_use2(
1308 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1309 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1310 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1311 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1312 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1313 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1314 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1315 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1316 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1317 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1318 ; CHECK-NEXT:    ret i8 [[NOT]]
1320   %nx = xor i8 %x, -1
1321   %ny = xor i8 %y, -1
1322   %nz = xor i8 %z, -1
1323   call void @use(i8 %nx)
1324   call void @use(i8 %ny)
1325   call void @use(i8 %nz)
1326   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1327   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1328   call void @use(i8 %m2)
1329   %not = xor i8 %m2, -1
1330   ret i8 %not
1333 define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {
1334 ; CHECK-LABEL: @freeToInvert_use3(
1335 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1336 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1337 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1338 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1339 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1340 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1341 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1342 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1343 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1344 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1345 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1346 ; CHECK-NEXT:    ret i8 [[NOT]]
1348   %nx = xor i8 %x, -1
1349   %ny = xor i8 %y, -1
1350   %nz = xor i8 %z, -1
1351   call void @use(i8 %nx)
1352   call void @use(i8 %ny)
1353   call void @use(i8 %nz)
1354   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1355   call void @use(i8 %m1)
1356   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1357   call void @use(i8 %m2)
1358   %not = xor i8 %m2, -1
1359   ret i8 %not
1362 define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) {
1363 ; CHECK-LABEL: @freeToInvert_two_minmax_ops(
1364 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1365 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1366 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1367 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1368 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1369 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1370 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1371 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1372 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1373 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]])
1374 ; CHECK-NEXT:    [[TMP3:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]])
1375 ; CHECK-NEXT:    ret i8 [[TMP3]]
1377   %nx = xor i8 %x, -1
1378   %ny = xor i8 %y, -1
1379   %nz = xor i8 %z, -1
1380   %nw = xor i8 %w, -1
1381   call void @use(i8 %nx)
1382   call void @use(i8 %ny)
1383   call void @use(i8 %nz)
1384   call void @use(i8 %nw)
1385   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1386   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1387   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1388   %not = xor i8 %m3, -1
1389   ret i8 %not
1392 define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) {
1393 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1(
1394 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1395 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1396 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1397 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1398 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1399 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1400 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1401 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1402 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1403 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1404 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1405 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1406 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1407 ; CHECK-NEXT:    ret i8 [[NOT]]
1409   %nx = xor i8 %x, -1
1410   %ny = xor i8 %y, -1
1411   %nz = xor i8 %z, -1
1412   %nw = xor i8 %w, -1
1413   call void @use(i8 %nx)
1414   call void @use(i8 %ny)
1415   call void @use(i8 %nz)
1416   call void @use(i8 %nw)
1417   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1418   call void @use(i8 %m1)
1419   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1420   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1421   %not = xor i8 %m3, -1
1422   ret i8 %not
1425 define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) {
1426 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2(
1427 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1428 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1429 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1430 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1431 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1432 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1433 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1434 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1435 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1436 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1437 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1438 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1439 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1440 ; CHECK-NEXT:    ret i8 [[NOT]]
1442   %nx = xor i8 %x, -1
1443   %ny = xor i8 %y, -1
1444   %nz = xor i8 %z, -1
1445   %nw = xor i8 %w, -1
1446   call void @use(i8 %nx)
1447   call void @use(i8 %ny)
1448   call void @use(i8 %nz)
1449   call void @use(i8 %nw)
1450   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1451   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1452   call void @use(i8 %m2)
1453   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1454   %not = xor i8 %m3, -1
1455   ret i8 %not
1458 define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
1459 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3(
1460 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1461 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1462 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1463 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1464 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1465 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1466 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1467 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1468 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1469 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1470 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1471 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1472 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1473 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1474 ; CHECK-NEXT:    ret i8 [[NOT]]
1476   %nx = xor i8 %x, -1
1477   %ny = xor i8 %y, -1
1478   %nz = xor i8 %z, -1
1479   %nw = xor i8 %w, -1
1480   call void @use(i8 %nx)
1481   call void @use(i8 %ny)
1482   call void @use(i8 %nz)
1483   call void @use(i8 %nw)
1484   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1485   call void @use(i8 %m1)
1486   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1487   call void @use(i8 %m2)
1488   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1489   %not = xor i8 %m3, -1
1490   ret i8 %not
1493 define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) {
1494 ; CHECK-LABEL: @sub_not_min_max(
1495 ; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1496 ; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1497 ; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1498 ; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1499 ; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1500 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1501 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1502 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1503 ; CHECK-NEXT:    ret i8 [[CK]]
1505   %notr = xor i8 %r, -1
1506   %notg = xor i8 %g, -1
1507   call void @use(i8 %notg)
1508   %notb = xor i8 %b, -1
1509   call void @use(i8 %notb)
1510   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1511   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1512   %ck = sub i8 %notr, %k
1513   ret i8 %ck
1516 define i8 @sub_not_min_max_uses1(i8 %r, i8 %g, i8 %b) {
1517 ; CHECK-LABEL: @sub_not_min_max_uses1(
1518 ; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1519 ; CHECK-NEXT:    call void @use(i8 [[NOTR]])
1520 ; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1521 ; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1522 ; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1523 ; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1524 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1525 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1526 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1527 ; CHECK-NEXT:    ret i8 [[CK]]
1529   %notr = xor i8 %r, -1
1530   call void @use(i8 %notr)
1531   %notg = xor i8 %g, -1
1532   call void @use(i8 %notg)
1533   %notb = xor i8 %b, -1
1534   call void @use(i8 %notb)
1535   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1536   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1537   %ck = sub i8 %notr, %k
1538   ret i8 %ck
1541 define i8 @sub_not_min_max_uses2(i8 %r, i8 %g, i8 %b) {
1542 ; CHECK-LABEL: @sub_not_min_max_uses2(
1543 ; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1544 ; CHECK-NEXT:    call void @use(i8 [[NOTR]])
1545 ; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1546 ; CHECK-NEXT:    call void @use(i8 [[NOTG]])
1547 ; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1548 ; CHECK-NEXT:    call void @use(i8 [[NOTB]])
1549 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1550 ; CHECK-NEXT:    call void @use(i8 [[M]])
1551 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1552 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1553 ; CHECK-NEXT:    ret i8 [[CK]]
1555   %notr = xor i8 %r, -1
1556   call void @use(i8 %notr)
1557   %notg = xor i8 %g, -1
1558   call void @use(i8 %notg)
1559   %notb = xor i8 %b, -1
1560   call void @use(i8 %notb)
1561   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1562   call void @use(i8 %m)
1563   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1564   %ck = sub i8 %notr, %k
1565   ret i8 %ck
1568 declare void @use4(i8, i8, i8, i8)
1570 define void @cmyk(i8 %r, i8 %g, i8 %b) {
1571 ; CHECK-LABEL: @cmyk(
1572 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1573 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1574 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1575 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1576 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1577 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1578 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1579 ; CHECK-NEXT:    ret void
1581   %notr = xor i8 %r, -1
1582   %notg = xor i8 %g, -1
1583   %notb = xor i8 %b, -1
1584   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1585   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1586   %ck = sub i8 %notr, %k
1587   %mk = sub i8 %notg, %k
1588   %yk = sub i8 %notb, %k
1589   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1590   ret void
1593 ; Same as above, but flip the operands of %k.
1595 define void @cmyk_commute1(i8 %r, i8 %g, i8 %b) {
1596 ; CHECK-LABEL: @cmyk_commute1(
1597 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1598 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1599 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1600 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1601 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1602 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1603 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1604 ; CHECK-NEXT:    ret void
1606   %notr = xor i8 %r, -1
1607   %notg = xor i8 %g, -1
1608   %notb = xor i8 %b, -1
1609   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1610   %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1611   %ck = sub i8 %notr, %k
1612   %mk = sub i8 %notg, %k
1613   %yk = sub i8 %notb, %k
1614   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1615   ret void
1618 ; Same as above, but also flip the operands of %m.
1620 define void @cmyk_commute2(i8 %r, i8 %g, i8 %b) {
1621 ; CHECK-LABEL: @cmyk_commute2(
1622 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1623 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1624 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1625 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1626 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1627 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1628 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1629 ; CHECK-NEXT:    ret void
1631   %notr = xor i8 %r, -1
1632   %notg = xor i8 %g, -1
1633   %notb = xor i8 %b, -1
1634   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1635   %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1636   %ck = sub i8 %notr, %k
1637   %mk = sub i8 %notg, %k
1638   %yk = sub i8 %notb, %k
1639   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1640   ret void
1643 ; Same as original, but only flip the operands of %m.
1645 define void @cmyk_commute3(i8 %r, i8 %g, i8 %b) {
1646 ; CHECK-LABEL: @cmyk_commute3(
1647 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1648 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1649 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1650 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1651 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1652 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1653 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1654 ; CHECK-NEXT:    ret void
1656   %notr = xor i8 %r, -1
1657   %notg = xor i8 %g, -1
1658   %notb = xor i8 %b, -1
1659   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1660   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1661   %ck = sub i8 %notr, %k
1662   %mk = sub i8 %notg, %k
1663   %yk = sub i8 %notb, %k
1664   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1665   ret void
1668 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1669 ; Also verify that we don't need matching min/max ops.
1671 define void @cmyk_commute4(i8 %r, i8 %g, i8 %b) {
1672 ; CHECK-LABEL: @cmyk_commute4(
1673 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1674 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1675 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1676 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1677 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1678 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1679 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1680 ; CHECK-NEXT:    ret void
1682   %notr = xor i8 %r, -1
1683   %notg = xor i8 %g, -1
1684   %notb = xor i8 %b, -1
1685   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1686   %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1687   %yk = sub i8 %notb, %k
1688   %ck = sub i8 %notr, %k
1689   %mk = sub i8 %notg, %k
1690   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1691   ret void
1694 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1695 ; Also verify that we don't need matching min/max ops.
1697 define void @cmyk_commute5(i8 %r, i8 %g, i8 %b) {
1698 ; CHECK-LABEL: @cmyk_commute5(
1699 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1700 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1701 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1702 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1703 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1704 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1705 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1706 ; CHECK-NEXT:    ret void
1708   %notr = xor i8 %r, -1
1709   %notg = xor i8 %g, -1
1710   %notb = xor i8 %b, -1
1711   %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1712   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1713   %ck = sub i8 %notr, %k
1714   %yk = sub i8 %notb, %k
1715   %mk = sub i8 %notg, %k
1716   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1717   ret void
1720 define void @cmyk_commute6(i8 %r, i8 %g, i8 %b) {
1721 ; CHECK-LABEL: @cmyk_commute6(
1722 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1723 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1724 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1725 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1726 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1727 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1728 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1729 ; CHECK-NEXT:    ret void
1731   %notr = xor i8 %r, -1
1732   %notg = xor i8 %g, -1
1733   %notb = xor i8 %b, -1
1734   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1735   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1736   %ck = sub i8 %k, %notr
1737   %mk = sub i8 %k, %notg
1738   %yk = sub i8 %k, %notb
1739   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1740   ret void
1743 ; Same as above, but flip the operands of %k.
1745 define void @cmyk_commute7(i8 %r, i8 %g, i8 %b) {
1746 ; CHECK-LABEL: @cmyk_commute7(
1747 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1748 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1749 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1750 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1751 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1752 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1753 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1754 ; CHECK-NEXT:    ret void
1756   %notr = xor i8 %r, -1
1757   %notg = xor i8 %g, -1
1758   %notb = xor i8 %b, -1
1759   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1760   %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1761   %ck = sub i8 %k, %notr
1762   %mk = sub i8 %k, %notg
1763   %yk = sub i8 %k, %notb
1764   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1765   ret void
1768 ; Same as above, but also flip the operands of %m.
1770 define void @cmyk_commute8(i8 %r, i8 %g, i8 %b) {
1771 ; CHECK-LABEL: @cmyk_commute8(
1772 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1773 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1774 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1775 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1776 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1777 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1778 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1779 ; CHECK-NEXT:    ret void
1781   %notr = xor i8 %r, -1
1782   %notg = xor i8 %g, -1
1783   %notb = xor i8 %b, -1
1784   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1785   %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1786   %ck = sub i8 %k, %notr
1787   %mk = sub i8 %k, %notg
1788   %yk = sub i8 %k, %notb
1789   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1790   ret void
1793 ; Same as original, but only flip the operands of %m.
1795 define void @cmyk_commute9(i8 %r, i8 %g, i8 %b) {
1796 ; CHECK-LABEL: @cmyk_commute9(
1797 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1798 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1799 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1800 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1801 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1802 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1803 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1804 ; CHECK-NEXT:    ret void
1806   %notr = xor i8 %r, -1
1807   %notg = xor i8 %g, -1
1808   %notb = xor i8 %b, -1
1809   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1810   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1811   %ck = sub i8 %k, %notr
1812   %mk = sub i8 %k, %notg
1813   %yk = sub i8 %k, %notb
1814   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1815   ret void
1818 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1819 ; Also verify that we don't need matching min/max ops.
1821 define void @cmyk_commute10(i8 %r, i8 %g, i8 %b) {
1822 ; CHECK-LABEL: @cmyk_commute10(
1823 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1824 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1825 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1826 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1827 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1828 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1829 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1830 ; CHECK-NEXT:    ret void
1832   %notr = xor i8 %r, -1
1833   %notg = xor i8 %g, -1
1834   %notb = xor i8 %b, -1
1835   %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1836   %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1837   %yk = sub i8 %notb, %k
1838   %ck = sub i8 %k, %notr
1839   %mk = sub i8 %notg, %k
1840   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1841   ret void
1844 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1845 ; Also verify that we don't need matching min/max ops.
1847 define void @cmyk_commute11(i8 %r, i8 %g, i8 %b) {
1848 ; CHECK-LABEL: @cmyk_commute11(
1849 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1850 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1851 ; CHECK-NEXT:    [[K:%.*]] = xor i8 [[TMP2]], -1
1852 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1853 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1854 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1855 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1856 ; CHECK-NEXT:    ret void
1858   %notr = xor i8 %r, -1
1859   %notg = xor i8 %g, -1
1860   %notb = xor i8 %b, -1
1861   %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1862   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1863   %ck = sub i8 %notr, %k
1864   %yk = sub i8 %k, %notb
1865   %mk = sub i8 %k, %notg
1866   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1867   ret void
1870 define i8 @smax_offset(i8 %x) {
1871 ; CHECK-LABEL: @smax_offset(
1872 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -127)
1873 ; CHECK-NEXT:    [[M:%.*]] = add nsw i8 [[TMP1]], 3
1874 ; CHECK-NEXT:    ret i8 [[M]]
1876   %a = add nsw i8 %x, 3
1877   %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1878   ret i8 %m
1881 ; This is handled by InstSimplify; testing here to confirm assert.
1883 define i8 @smax_offset_limit(i8 %x) {
1884 ; CHECK-LABEL: @smax_offset_limit(
1885 ; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1886 ; CHECK-NEXT:    ret i8 [[A]]
1888   %a = add nsw i8 %x, 3
1889   %m = call i8 @llvm.smax.i8(i8 %a, i8 -125)
1890   ret i8 %m
1893 ; This is handled by InstSimplify; testing here to confirm assert.
1895 define i8 @smax_offset_overflow(i8 %x) {
1896 ; CHECK-LABEL: @smax_offset_overflow(
1897 ; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1898 ; CHECK-NEXT:    ret i8 [[A]]
1900   %a = add nsw i8 %x, 3
1901   %m = call i8 @llvm.smax.i8(i8 %a, i8 -126)
1902   ret i8 %m
1905 ; negative test - require nsw
1907 define i8 @smax_offset_may_wrap(i8 %x) {
1908 ; CHECK-LABEL: @smax_offset_may_wrap(
1909 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], 3
1910 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1911 ; CHECK-NEXT:    ret i8 [[M]]
1913   %a = add i8 %x, 3
1914   %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1915   ret i8 %m
1918 ; negative test
1920 define i8 @smax_offset_uses(i8 %x) {
1921 ; CHECK-LABEL: @smax_offset_uses(
1922 ; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1923 ; CHECK-NEXT:    call void @use(i8 [[A]])
1924 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1925 ; CHECK-NEXT:    ret i8 [[M]]
1927   %a = add nsw i8 %x, 3
1928   call void @use(i8 %a)
1929   %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1930   ret i8 %m
1933 define <3 x i8> @smin_offset(<3 x i8> %x) {
1934 ; CHECK-LABEL: @smin_offset(
1935 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -127, i8 -127, i8 -127>)
1936 ; CHECK-NEXT:    [[M:%.*]] = or <3 x i8> [[TMP1]], <i8 124, i8 124, i8 124>
1937 ; CHECK-NEXT:    ret <3 x i8> [[M]]
1939   %a = add nsw nuw <3 x i8> %x, <i8 124, i8 124, i8 124>
1940   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %a, <3 x i8> <i8 -3, i8 -3, i8 -3>)
1941   ret <3 x i8> %m
1944 ; This is handled by InstSimplify; testing here to confirm assert.
1946 define i8 @smin_offset_limit(i8 %x) {
1947 ; CHECK-LABEL: @smin_offset_limit(
1948 ; CHECK-NEXT:    ret i8 -3
1950   %a = add nsw i8 %x, 125
1951   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1952   ret i8 %m
1955 ; This is handled by InstSimplify; testing here to confirm assert.
1957 define i8 @smin_offset_overflow(i8 %x) {
1958 ; CHECK-LABEL: @smin_offset_overflow(
1959 ; CHECK-NEXT:    ret i8 -3
1961   %a = add nsw i8 %x, 126
1962   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1963   ret i8 %m
1966 ; negative test - require nsw
1968 define i8 @smin_offset_may_wrap(i8 %x) {
1969 ; CHECK-LABEL: @smin_offset_may_wrap(
1970 ; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 124
1971 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1972 ; CHECK-NEXT:    ret i8 [[M]]
1974   %a = add nuw i8 %x, 124
1975   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1976   ret i8 %m
1979 ; negative test
1981 define i8 @smin_offset_uses(i8 %x) {
1982 ; CHECK-LABEL: @smin_offset_uses(
1983 ; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], 124
1984 ; CHECK-NEXT:    call void @use(i8 [[A]])
1985 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1986 ; CHECK-NEXT:    ret i8 [[M]]
1988   %a = add nsw i8 %x, 124
1989   call void @use(i8 %a)
1990   %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1991   ret i8 %m
1994 ; Note: 'nsw' must not propagate here.
1996 define <3 x i8> @umax_offset(<3 x i8> %x) {
1997 ; CHECK-LABEL: @umax_offset(
1998 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 3, i8 3, i8 3>)
1999 ; CHECK-NEXT:    [[M:%.*]] = add nuw <3 x i8> [[TMP1]], <i8 127, i8 127, i8 127>
2000 ; CHECK-NEXT:    ret <3 x i8> [[M]]
2002   %a = add nsw nuw <3 x i8> %x, <i8 127, i8 127, i8 127>
2003   %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 130, i8 130, i8 130>)
2004   ret <3 x i8> %m
2007 ; This is handled by InstSimplify; testing here to confirm assert.
2009 define i8 @umax_offset_limit(i8 %x) {
2010 ; CHECK-LABEL: @umax_offset_limit(
2011 ; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2012 ; CHECK-NEXT:    ret i8 [[A]]
2014   %a = add nuw i8 %x, 3
2015   %m = call i8 @llvm.umax.i8(i8 %a, i8 3)
2016   ret i8 %m
2019 ; This is handled by InstSimplify; testing here to confirm assert.
2021 define i8 @umax_offset_overflow(i8 %x) {
2022 ; CHECK-LABEL: @umax_offset_overflow(
2023 ; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2024 ; CHECK-NEXT:    ret i8 [[A]]
2026   %a = add nuw i8 %x, 3
2027   %m = call i8 @llvm.umax.i8(i8 %a, i8 2)
2028   ret i8 %m
2031 ; negative test - require nuw
2033 define i8 @umax_offset_may_wrap(i8 %x) {
2034 ; CHECK-LABEL: @umax_offset_may_wrap(
2035 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], 3
2036 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2037 ; CHECK-NEXT:    ret i8 [[M]]
2039   %a = add i8 %x, 3
2040   %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2041   ret i8 %m
2044 ; negative test
2046 define i8 @umax_offset_uses(i8 %x) {
2047 ; CHECK-LABEL: @umax_offset_uses(
2048 ; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2049 ; CHECK-NEXT:    call void @use(i8 [[A]])
2050 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2051 ; CHECK-NEXT:    ret i8 [[M]]
2053   %a = add nuw i8 %x, 3
2054   call void @use(i8 %a)
2055   %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2056   ret i8 %m
2059 define i8 @umin_offset(i8 %x) {
2060 ; CHECK-LABEL: @umin_offset(
2061 ; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[X:%.*]], 0
2062 ; CHECK-NEXT:    [[M:%.*]] = select i1 [[DOTNOT]], i8 -5, i8 -4
2063 ; CHECK-NEXT:    ret i8 [[M]]
2065   %a = add nuw i8 %x, 251
2066   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2067   ret i8 %m
2070 ; This is handled by InstSimplify; testing here to confirm assert.
2072 define i8 @umin_offset_limit(i8 %x) {
2073 ; CHECK-LABEL: @umin_offset_limit(
2074 ; CHECK-NEXT:    ret i8 -4
2076   %a = add nuw i8 %x, 252
2077   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2078   ret i8 %m
2081 ; This is handled by InstSimplify; testing here to confirm assert.
2083 define i8 @umin_offset_overflow(i8 %x) {
2084 ; CHECK-LABEL: @umin_offset_overflow(
2085 ; CHECK-NEXT:    ret i8 -4
2087   %a = add nuw i8 %x, 253
2088   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2089   ret i8 %m
2092 ; negative test - require nuw
2094 define i8 @umin_offset_may_wrap(i8 %x) {
2095 ; CHECK-LABEL: @umin_offset_may_wrap(
2096 ; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[X:%.*]], -5
2097 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2098 ; CHECK-NEXT:    ret i8 [[M]]
2100   %a = add nsw i8 %x, 251
2101   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2102   ret i8 %m
2105 ; negative test
2107 define i8 @umin_offset_uses(i8 %x) {
2108 ; CHECK-LABEL: @umin_offset_uses(
2109 ; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[X:%.*]], -5
2110 ; CHECK-NEXT:    call void @use(i8 [[A]])
2111 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2112 ; CHECK-NEXT:    ret i8 [[M]]
2114   %a = add nuw i8 %x, 251
2115   call void @use(i8 %a)
2116   %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2117   ret i8 %m
2120 ; TODO: This could transform, but undef element must not propagate to the new add.
2122 define <3 x i8> @umax_vector_splat_undef(<3 x i8> %x) {
2123 ; CHECK-LABEL: @umax_vector_splat_undef(
2124 ; CHECK-NEXT:    [[A:%.*]] = add nuw <3 x i8> [[X:%.*]], <i8 undef, i8 64, i8 64>
2125 ; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[A]], <3 x i8> <i8 13, i8 -126, i8 -126>)
2126 ; CHECK-NEXT:    ret <3 x i8> [[R]]
2128   %a = add nuw <3 x i8> %x, <i8 undef, i8 64, i8 64>
2129   %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 13, i8 130, i8 130>)
2130   ret <3 x i8> %r
2133 ; Issue #52884 - this would assert because of a failure to simplify.
2135 define i8 @smax_offset_simplify(i8 %x) {
2136 ; CHECK-LABEL: @smax_offset_simplify(
2137 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i8 [[X:%.*]], 50
2138 ; CHECK-NEXT:    ret i8 [[TMP1]]
2140   %1 = add nuw nsw i8 50, %x
2141   %m = call i8 @llvm.smax.i8(i8 %1, i8 -124)
2142   ret i8 %m