[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / minmax-intrinsics.ll
blob2e4224b11ccf9166f273563c801a34ee20b8d23d
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 [[X]], i8 [[Y:%.*]])
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 ; Negative test - too many uses
511 define i8 @umin_of_not_and_const_uses(i8 %x) {
512 ; CHECK-LABEL: @umin_of_not_and_const_uses(
513 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
514 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
515 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45)
516 ; CHECK-NEXT:    ret i8 [[M]]
518   %notx = xor i8 %x, -1
519   call void @use(i8 %notx)
520   %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
521   ret i8 %m
524 define i8 @not_smax_of_nots(i8 %x, i8 %y) {
525 ; CHECK-LABEL: @not_smax_of_nots(
526 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
527 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
528 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
529 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
530 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
531 ; CHECK-NEXT:    ret i8 [[TMP1]]
533   %notx = xor i8 %x, -1
534   call void @use(i8 %notx)
535   %noty = xor i8 %y, -1
536   call void @use(i8 %noty)
537   %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
538   %notm = xor i8 %m, -1
539   ret i8 %notm
542 define i8 @not_smin_of_nots(i8 %x, i8 %y) {
543 ; CHECK-LABEL: @not_smin_of_nots(
544 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
545 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
546 ; CHECK-NEXT:    [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
547 ; CHECK-NEXT:    call void @use(i8 [[NOTY]])
548 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]])
549 ; CHECK-NEXT:    call void @use(i8 [[M]])
550 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
551 ; CHECK-NEXT:    ret i8 [[NOTM]]
553   %notx = xor i8 %x, -1
554   call void @use(i8 %notx)
555   %noty = xor i8 %y, -1
556   call void @use(i8 %noty)
557   %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty)
558   call void @use(i8 %m)
559   %notm = xor i8 %m, -1
560   ret i8 %notm
563 define i8 @not_umax_of_not(i8 %x, i8 %y) {
564 ; CHECK-LABEL: @not_umax_of_not(
565 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
566 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
567 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
568 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])
569 ; CHECK-NEXT:    ret i8 [[TMP2]]
571   %notx = xor i8 %x, -1
572   call void @use(i8 %notx)
573   %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)
574   %notm = xor i8 %m, -1
575   ret i8 %notm
578 ; Negative test - this would require an extra instruction.
580 define i8 @not_umin_of_not(i8 %x, i8 %y) {
581 ; CHECK-LABEL: @not_umin_of_not(
582 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
583 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
584 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]])
585 ; CHECK-NEXT:    call void @use(i8 [[M]])
586 ; CHECK-NEXT:    [[NOTM:%.*]] = xor i8 [[M]], -1
587 ; CHECK-NEXT:    ret i8 [[NOTM]]
589   %notx = xor i8 %x, -1
590   call void @use(i8 %notx)
591   %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y)
592   call void @use(i8 %m)
593   %notm = xor i8 %m, -1
594   ret i8 %notm
597 define i8 @not_umin_of_not_constant_op(i8 %x) {
598 ; CHECK-LABEL: @not_umin_of_not_constant_op(
599 ; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
600 ; CHECK-NEXT:    call void @use(i8 [[NOTX]])
601 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43)
602 ; CHECK-NEXT:    ret i8 [[TMP1]]
604   %notx = xor i8 %x, -1
605   call void @use(i8 %notx)
606   %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)
607   %notm = xor i8 %m, -1
608   ret i8 %notm
611 define i8 @smax_negation(i8 %x, i8 %y) {
612 ; CHECK-LABEL: @smax_negation(
613 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
614 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
615 ; CHECK-NEXT:    ret i8 [[TMP1]]
617   %s1 = sub i8 %x, %y
618   %s2 = sub i8 %y, %x
619   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
620   ret i8 %r
623 define i8 @smax_negation_nsw(i8 %x, i8 %y) {
624 ; CHECK-LABEL: @smax_negation_nsw(
625 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
626 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
627 ; CHECK-NEXT:    ret i8 [[TMP1]]
629   %s1 = sub nsw i8 %x, %y
630   %s2 = sub nsw i8 %y, %x
631   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
632   ret i8 %r
635 define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
636 ; CHECK-LABEL: @smax_negation_not_nsw(
637 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
638 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
639 ; CHECK-NEXT:    ret i8 [[TMP1]]
641   %s1 = sub nsw i8 %x, %y
642   %s2 = sub nuw i8 %y, %x
643   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
644   ret i8 %r
647 define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
648 ; CHECK-LABEL: @smax_negation_vec(
649 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
650 ; CHECK-NEXT:    ret <3 x i8> [[TMP1]]
652   %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
653   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
654   ret <3 x i8> %r
657 define i8 @smin_negation(i8 %x, i8 %y) {
658 ; CHECK-LABEL: @smin_negation(
659 ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
660 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
661 ; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
662 ; CHECK-NEXT:    ret i8 [[NABS]]
664   %s1 = sub i8 %x, %y
665   %s2 = sub i8 %y, %x
666   %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)
667   ret i8 %r
670 define i8 @umax_negation(i8 %x, i8 %y) {
671 ; CHECK-LABEL: @umax_negation(
672 ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
673 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
674 ; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
675 ; CHECK-NEXT:    ret i8 [[NABS]]
677   %s1 = sub nsw i8 %x, %y
678   %s2 = sub nsw i8 %y, %x
679   %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)
680   ret i8 %r
683 define i8 @umin_negation(i8 %x) {
684 ; CHECK-LABEL: @umin_negation(
685 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
686 ; CHECK-NEXT:    ret i8 [[TMP1]]
688   %s = sub nsw i8 0, %x
689   %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
690   ret i8 %r
693 define i8 @smax_negation_uses(i8 %x, i8 %y) {
694 ; CHECK-LABEL: @smax_negation_uses(
695 ; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
696 ; CHECK-NEXT:    call void @use(i8 [[S2]])
697 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false)
698 ; CHECK-NEXT:    ret i8 [[TMP1]]
700   %s1 = sub i8 %x, %y
701   %s2 = sub i8 %y, %x
702   call void @use(i8 %s2)
703   %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
704   ret i8 %r
707 define i8 @clamp_two_vals_smax_smin(i8 %x) {
708 ; CHECK-LABEL: @clamp_two_vals_smax_smin(
709 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43
710 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
711 ; CHECK-NEXT:    ret i8 [[R]]
713   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
714   %r = call i8 @llvm.smin.i8(i8 %m, i8 43)
715   ret i8 %r
718 define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) {
719 ; CHECK-LABEL: @clamp_two_vals_smin_smax(
720 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 41, i8 41, i8 41>
721 ; 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>
722 ; CHECK-NEXT:    ret <3 x i8> [[R]]
724   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)
725   %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)
726   ret <3 x i8> %r
729 define i8 @clamp_two_vals_umax_umin(i8 %x) {
730 ; CHECK-LABEL: @clamp_two_vals_umax_umin(
731 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43
732 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
733 ; CHECK-NEXT:    ret i8 [[R]]
735   %m = call i8 @llvm.umax.i8(i8 %x, i8 42)
736   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
737   ret i8 %r
740 define i8 @clamp_two_vals_umin_umax(i8 %x) {
741 ; CHECK-LABEL: @clamp_two_vals_umin_umax(
742 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41
743 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41
744 ; CHECK-NEXT:    ret i8 [[R]]
746   %m = call i8 @llvm.umin.i8(i8 %x, i8 42)
747   %r = call i8 @llvm.umax.i8(i8 %m, i8 41)
748   ret i8 %r
751 ; Negative test - mismatched signs
753 define i8 @clamp_two_vals_smax_umin(i8 %x) {
754 ; CHECK-LABEL: @clamp_two_vals_smax_umin(
755 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
756 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43)
757 ; CHECK-NEXT:    ret i8 [[R]]
759   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
760   %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
761   ret i8 %r
764 ; Negative test - wrong range
766 define i8 @clamp_three_vals_smax_smin(i8 %x) {
767 ; CHECK-LABEL: @clamp_three_vals_smax_smin(
768 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
769 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44)
770 ; CHECK-NEXT:    ret i8 [[R]]
772   %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
773   %r = call i8 @llvm.smin.i8(i8 %m, i8 44)
774   ret i8 %r
777 ; Edge cases are simplified
779 define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
780 ; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
781 ; CHECK-NEXT:    ret i8 0
783   %m = call i8 @llvm.umax.i8(i8 %x, i8 255)
784   %r = call i8 @llvm.umin.i8(i8 %m, i8 0)
785   ret i8 %r
788 ; Edge cases are simplified
790 define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
791 ; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
792 ; CHECK-NEXT:    ret i8 -1
794   %m = call i8 @llvm.umin.i8(i8 %x, i8 0)
795   %r = call i8 @llvm.umax.i8(i8 %m, i8 255)
796   ret i8 %r
799 ; Edge cases are simplified
801 define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
802 ; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
803 ; CHECK-NEXT:    ret i8 -128
805   %m = call i8 @llvm.smax.i8(i8 %x, i8 127)
806   %r = call i8 @llvm.smin.i8(i8 %m, i8 128)
807   ret i8 %r
810 ; Edge cases are simplified
812 define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
813 ; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
814 ; CHECK-NEXT:    ret i8 127
816   %m = call i8 @llvm.smin.i8(i8 %x, i8 128)
817   %r = call i8 @llvm.smax.i8(i8 %m, i8 127)
818   ret i8 %r
822 define i8 @umin_non_zero_idiom1(i8 %a) {
823 ; CHECK-LABEL: @umin_non_zero_idiom1(
824 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
825 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
826 ; CHECK-NEXT:    ret i8 [[RES]]
828   %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
829   ret i8 %res
832 define i8 @umin_non_zero_idiom2(i8 %a) {
833 ; CHECK-LABEL: @umin_non_zero_idiom2(
834 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
835 ; CHECK-NEXT:    [[RES:%.*]] = zext i1 [[TMP1]] to i8
836 ; CHECK-NEXT:    ret i8 [[RES]]
838   %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
839   ret i8 %res
842 define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
843 ; CHECK-LABEL: @umin_non_zero_idiom3(
844 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
845 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
846 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
848   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
849   ret <3 x i8> %res
852 define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
853 ; CHECK-LABEL: @umin_non_zero_idiom4(
854 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
855 ; CHECK-NEXT:    [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
856 ; CHECK-NEXT:    ret <3 x i8> [[RES]]
858   %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 undef, i8 undef>)
859   ret <3 x i8> %res
862 define i1 @umin_eq_zero(i8 %a, i8 %b) {
863 ; CHECK-LABEL: @umin_eq_zero(
864 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
865 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i8 [[UMIN]], 0
866 ; CHECK-NEXT:    ret i1 [[RES]]
868   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
869   %res = icmp eq i8 %umin, 0
870   ret i1 %res
873 define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) {
874 ; CHECK-LABEL: @umin_eq_zero2(
875 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
876 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer
877 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
880   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
881   %res = icmp eq <3 x i8> %umin, zeroinitializer
882   ret <3 x i1> %res
885 define i1 @umin_ne_zero(i8 %a, i8 %b) {
886 ; CHECK-LABEL: @umin_ne_zero(
887 ; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
888 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8 [[UMIN]], 0
889 ; CHECK-NEXT:    ret i1 [[RES]]
891   %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
892   %res = icmp ne i8 %umin, 0
893   ret i1 %res
896 define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) {
897 ; CHECK-LABEL: @umin_ne_zero2(
898 ; CHECK-NEXT:    [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
899 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer
900 ; CHECK-NEXT:    ret <3 x i1> [[RES]]
903   %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
904   %res = icmp ne <3 x i8> %umin, zeroinitializer
905   ret <3 x i1> %res
908 define i8 @smax(i8 %x, i8 %y, i8 %z) {
909 ; CHECK-LABEL: @smax(
910 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]])
911 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]])
912 ; CHECK-NEXT:    ret i8 [[M3]]
914   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
915   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
916   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
917   ret i8 %m3
920 define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
921 ; CHECK-LABEL: @smin(
922 ; CHECK-NEXT:    [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]])
923 ; CHECK-NEXT:    [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]])
924 ; CHECK-NEXT:    ret <3 x i8> [[M3]]
926   %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)
927   %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)
928   %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)
929   ret <3 x i8> %m3
932 define i8 @umax(i8 %x, i8 %y, i8 %z) {
933 ; CHECK-LABEL: @umax(
934 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
935 ; CHECK-NEXT:    call void @use(i8 [[M1]])
936 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]])
937 ; CHECK-NEXT:    ret i8 [[M3]]
939   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
940   call void @use(i8 %m1)
941   %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)
942   %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)
943   ret i8 %m3
946 define i8 @umin(i8 %x, i8 %y, i8 %z) {
947 ; CHECK-LABEL: @umin(
948 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]])
949 ; CHECK-NEXT:    call void @use(i8 [[M2]])
950 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]])
951 ; CHECK-NEXT:    ret i8 [[M3]]
953   %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
954   %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)
955   call void @use(i8 %m2)
956   %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)
957   ret i8 %m3
960 ; negative test - too many uses
962 define i8 @smax_uses(i8 %x, i8 %y, i8 %z) {
963 ; CHECK-LABEL: @smax_uses(
964 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
965 ; CHECK-NEXT:    call void @use(i8 [[M1]])
966 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]])
967 ; CHECK-NEXT:    call void @use(i8 [[M2]])
968 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
969 ; CHECK-NEXT:    ret i8 [[M3]]
971   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
972   call void @use(i8 %m1)
973   %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
974   call void @use(i8 %m2)
975   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
976   ret i8 %m3
979 ; negative test - must have common operand
981 define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) {
982 ; CHECK-LABEL: @smax_no_common_op(
983 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
984 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]])
985 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
986 ; CHECK-NEXT:    ret i8 [[M3]]
988   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
989   %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)
990   %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
991   ret i8 %m3
994 define i8 @umax_demand_lshr(i8 %x) {
995 ; CHECK-LABEL: @umax_demand_lshr(
996 ; CHECK-NEXT:    [[R:%.*]] = lshr i8 [[X:%.*]], 4
997 ; CHECK-NEXT:    ret i8 [[R]]
999   %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1000   %r = lshr i8 %m, 4
1001   ret i8 %r
1004 define i8 @umax_demand_and(i8 %x) {
1005 ; CHECK-LABEL: @umax_demand_and(
1006 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], 10
1007 ; CHECK-NEXT:    ret i8 [[R]]
1009   %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1010   %r = and i8 %m, 10
1011   ret i8 %r
1014 define i8 @umin_demand_or_31_30(i8 %x) {
1015 ; CHECK-LABEL: @umin_demand_or_31_30(
1016 ; CHECK-NEXT:    [[R:%.*]] = or i8 [[X:%.*]], 31
1017 ; CHECK-NEXT:    ret i8 [[R]]
1019   %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1020   %r = or i8 %m, 31
1021   ret i8 %r
1024 define i8 @umin_demand_and_7_8(i8 %x) {
1025 ; CHECK-LABEL: @umin_demand_and_7_8(
1026 ; CHECK-NEXT:    [[R:%.*]] = and i8 [[X:%.*]], -8
1027 ; CHECK-NEXT:    ret i8 [[R]]
1029   %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1030   %r = and i8 %m, -8
1031   ret i8 %r
1034 define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) {
1035 ; CHECK-LABEL: @neg_neg_nsw_smax(
1036 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1037 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1038 ; CHECK-NEXT:    ret i8 [[M]]
1040   %nx = sub nsw i8 0, %x
1041   %ny = sub nsw i8 0, %y
1042   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1043   ret i8 %m
1046 define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) {
1047 ; CHECK-LABEL: @neg_neg_nsw_smin(
1048 ; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
1049 ; CHECK-NEXT:    [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]]
1050 ; CHECK-NEXT:    ret <3 x i8> [[M]]
1052   %nx = sub nsw <3 x i8> zeroinitializer, %x
1053   %ny = sub nsw <3 x i8> zeroinitializer, %y
1054   %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)
1055   ret <3 x i8> %m
1058 define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) {
1059 ; CHECK-LABEL: @neg_neg_nsw_smax_use0(
1060 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1061 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1062 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]])
1063 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1064 ; CHECK-NEXT:    ret i8 [[M]]
1066   %nx = sub nsw i8 0, %x
1067   call void @use(i8 %nx)
1068   %ny = sub nsw i8 0, %y
1069   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1070   ret i8 %m
1073 define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) {
1074 ; CHECK-LABEL: @neg_neg_nsw_smin_use1(
1075 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1076 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1077 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]])
1078 ; CHECK-NEXT:    [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1079 ; CHECK-NEXT:    ret i8 [[M]]
1081   %nx = sub nsw i8 0, %x
1082   %ny = sub nsw i8 0, %y
1083   call void @use(i8 %ny)
1084   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1085   ret i8 %m
1088 ; negative test - too many uses
1090 define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) {
1091 ; CHECK-LABEL: @neg_neg_nsw_smin_use2(
1092 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1093 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1094 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1095 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1096 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1097 ; CHECK-NEXT:    ret i8 [[M]]
1099   %nx = sub nsw i8 0, %x
1100   call void @use(i8 %nx)
1101   %ny = sub nsw i8 0, %y
1102   call void @use(i8 %ny)
1103   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1104   ret i8 %m
1107 ; negative test - need nsw on both ops
1109 define i8 @neg_neg_smax(i8 %x, i8 %y) {
1110 ; CHECK-LABEL: @neg_neg_smax(
1111 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1112 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1113 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]])
1114 ; CHECK-NEXT:    ret i8 [[M]]
1116   %nx = sub i8 0, %x
1117   %ny = sub nsw i8 0, %y
1118   %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1119   ret i8 %m
1122 ; negative test - need nsw on both ops
1124 define i8 @neg_neg_smin(i8 %x, i8 %y) {
1125 ; CHECK-LABEL: @neg_neg_smin(
1126 ; CHECK-NEXT:    [[NX:%.*]] = sub i8 0, [[X:%.*]]
1127 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1128 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1129 ; CHECK-NEXT:    ret i8 [[M]]
1131   %nx = sub i8 0, %x
1132   %ny = sub nsw i8 0, %y
1133   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1134   ret i8 %m
1137 ; negative test - need signed min/max
1139 define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) {
1140 ; CHECK-LABEL: @neg_neg_nsw_umin(
1141 ; CHECK-NEXT:    [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1142 ; CHECK-NEXT:    [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1143 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
1144 ; CHECK-NEXT:    ret i8 [[M]]
1146   %nx = sub nsw i8 0, %x
1147   %ny = sub nsw i8 0, %y
1148   %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
1149   ret i8 %m
1152 define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {
1153 ; CHECK-LABEL: @freeToInvertSub(
1154 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1155 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1156 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1157 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1158 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1159 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1160 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1161 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1162 ; CHECK-NEXT:    ret i8 [[SUB]]
1164   %nx = xor i8 %x, -1
1165   %ny = xor i8 %y, -1
1166   %nz = xor i8 %z, -1
1167   call void @use(i8 %nx)
1168   call void @use(i8 %ny)
1169   call void @use(i8 %nz)
1170   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1171   %sub = sub i8 %nz, %m
1172   ret i8 %sub
1175 define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {
1176 ; CHECK-LABEL: @freeToInvertSub_uses(
1177 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1178 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1179 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1180 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1181 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1182 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1183 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1184 ; CHECK-NEXT:    call void @use(i8 [[M]])
1185 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1186 ; CHECK-NEXT:    ret i8 [[SUB]]
1188   %nx = xor i8 %x, -1
1189   %ny = xor i8 %y, -1
1190   %nz = xor i8 %z, -1
1191   call void @use(i8 %nx)
1192   call void @use(i8 %ny)
1193   call void @use(i8 %nz)
1194   %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1195   call void @use(i8 %m)
1196   %sub = sub i8 %nz, %m
1197   ret i8 %sub
1200 define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {
1201 ; CHECK-LABEL: @freeToInvert(
1202 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1203 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1204 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1205 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1206 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1207 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1208 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1209 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[Z]])
1210 ; CHECK-NEXT:    ret i8 [[TMP2]]
1212   %nx = xor i8 %x, -1
1213   %ny = xor i8 %y, -1
1214   %nz = xor i8 %z, -1
1215   call void @use(i8 %nx)
1216   call void @use(i8 %ny)
1217   call void @use(i8 %nz)
1218   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1219   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1220   %not = xor i8 %m2, -1
1221   ret i8 %not
1224 define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {
1225 ; CHECK-LABEL: @freeToInvert_use1(
1226 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1227 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1228 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1229 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1230 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1231 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1232 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1233 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1234 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[M1]], -1
1235 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1236 ; CHECK-NEXT:    ret i8 [[TMP2]]
1238   %nx = xor i8 %x, -1
1239   %ny = xor i8 %y, -1
1240   %nz = xor i8 %z, -1
1241   call void @use(i8 %nx)
1242   call void @use(i8 %ny)
1243   call void @use(i8 %nz)
1244   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1245   call void @use(i8 %m1)
1246   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1247   %not = xor i8 %m2, -1
1248   ret i8 %not
1251 define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {
1252 ; CHECK-LABEL: @freeToInvert_use2(
1253 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1254 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1255 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1256 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1257 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1258 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1259 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1260 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1261 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1262 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1263 ; CHECK-NEXT:    ret i8 [[NOT]]
1265   %nx = xor i8 %x, -1
1266   %ny = xor i8 %y, -1
1267   %nz = xor i8 %z, -1
1268   call void @use(i8 %nx)
1269   call void @use(i8 %ny)
1270   call void @use(i8 %nz)
1271   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1272   %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1273   call void @use(i8 %m2)
1274   %not = xor i8 %m2, -1
1275   ret i8 %not
1278 define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {
1279 ; CHECK-LABEL: @freeToInvert_use3(
1280 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1281 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1282 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1283 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1284 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1285 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1286 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1287 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1288 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1289 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1290 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M2]], -1
1291 ; CHECK-NEXT:    ret i8 [[NOT]]
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   call void @use(i8 %m2)
1303   %not = xor i8 %m2, -1
1304   ret i8 %not
1307 define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) {
1308 ; CHECK-LABEL: @freeToInvert_two_minmax_ops(
1309 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1310 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1311 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1312 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -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:    call void @use(i8 [[NW]])
1317 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1318 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]])
1319 ; CHECK-NEXT:    [[TMP3:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]])
1320 ; CHECK-NEXT:    ret i8 [[TMP3]]
1322   %nx = xor i8 %x, -1
1323   %ny = xor i8 %y, -1
1324   %nz = xor i8 %z, -1
1325   %nw = xor i8 %w, -1
1326   call void @use(i8 %nx)
1327   call void @use(i8 %ny)
1328   call void @use(i8 %nz)
1329   call void @use(i8 %nw)
1330   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1331   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1332   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1333   %not = xor i8 %m3, -1
1334   ret i8 %not
1337 define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) {
1338 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1(
1339 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1340 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1341 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1342 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1343 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1344 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1345 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1346 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1347 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1348 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1349 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1350 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1351 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1352 ; CHECK-NEXT:    ret i8 [[NOT]]
1354   %nx = xor i8 %x, -1
1355   %ny = xor i8 %y, -1
1356   %nz = xor i8 %z, -1
1357   %nw = xor i8 %w, -1
1358   call void @use(i8 %nx)
1359   call void @use(i8 %ny)
1360   call void @use(i8 %nz)
1361   call void @use(i8 %nw)
1362   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1363   call void @use(i8 %m1)
1364   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1365   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1366   %not = xor i8 %m3, -1
1367   ret i8 %not
1370 define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) {
1371 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2(
1372 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1373 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1374 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1375 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1376 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1377 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1378 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1379 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1380 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1381 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1382 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1383 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1384 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1385 ; CHECK-NEXT:    ret i8 [[NOT]]
1387   %nx = xor i8 %x, -1
1388   %ny = xor i8 %y, -1
1389   %nz = xor i8 %z, -1
1390   %nw = xor i8 %w, -1
1391   call void @use(i8 %nx)
1392   call void @use(i8 %ny)
1393   call void @use(i8 %nz)
1394   call void @use(i8 %nw)
1395   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1396   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1397   call void @use(i8 %m2)
1398   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1399   %not = xor i8 %m3, -1
1400   ret i8 %not
1403 define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
1404 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3(
1405 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
1406 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1407 ; CHECK-NEXT:    [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1408 ; CHECK-NEXT:    [[NW:%.*]] = xor i8 [[W:%.*]], -1
1409 ; CHECK-NEXT:    call void @use(i8 [[NX]])
1410 ; CHECK-NEXT:    call void @use(i8 [[NY]])
1411 ; CHECK-NEXT:    call void @use(i8 [[NZ]])
1412 ; CHECK-NEXT:    call void @use(i8 [[NW]])
1413 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1414 ; CHECK-NEXT:    call void @use(i8 [[M1]])
1415 ; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1416 ; CHECK-NEXT:    call void @use(i8 [[M2]])
1417 ; CHECK-NEXT:    [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1418 ; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[M3]], -1
1419 ; CHECK-NEXT:    ret i8 [[NOT]]
1421   %nx = xor i8 %x, -1
1422   %ny = xor i8 %y, -1
1423   %nz = xor i8 %z, -1
1424   %nw = xor i8 %w, -1
1425   call void @use(i8 %nx)
1426   call void @use(i8 %ny)
1427   call void @use(i8 %nz)
1428   call void @use(i8 %nw)
1429   %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1430   call void @use(i8 %m1)
1431   %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1432   call void @use(i8 %m2)
1433   %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1434   %not = xor i8 %m3, -1
1435   ret i8 %not
1438 declare void @use4(i8, i8, i8, i8)
1440 define void @cmyk(i8 %r, i8 %g, i8 %b) {
1441 ; CHECK-LABEL: @cmyk(
1442 ; CHECK-NEXT:    [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1443 ; CHECK-NEXT:    [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1444 ; CHECK-NEXT:    [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1445 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1446 ; CHECK-NEXT:    [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1447 ; CHECK-NEXT:    [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1448 ; CHECK-NEXT:    [[MK:%.*]] = sub i8 [[NOTG]], [[K]]
1449 ; CHECK-NEXT:    [[YK:%.*]] = sub i8 [[NOTB]], [[K]]
1450 ; CHECK-NEXT:    call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1451 ; CHECK-NEXT:    ret void
1453   %notr = xor i8 %r, -1
1454   %notg = xor i8 %g, -1
1455   %notb = xor i8 %b, -1
1456   %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1457   %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1458   %ck = sub i8 %notr, %k
1459   %mk = sub i8 %notg, %k
1460   %yk = sub i8 %notb, %k
1461   call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1462   ret void