1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare i1 @llvm.umin.i1(i1, i1)
5 declare i8 @llvm.umin.i8(i8, i8)
6 declare i8 @llvm.umax.i8(i8, i8)
7 declare i8 @llvm.smin.i8(i8, i8)
8 declare i8 @llvm.smax.i8(i8, i8)
9 declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)
10 declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)
11 declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)
12 declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)
14 declare void @use_vec(<3 x i8>)
16 define i8 @umin_known_bits(i8 %x, i8 %y) {
17 ; CHECK-LABEL: @umin_known_bits(
18 ; CHECK-NEXT: ret i8 0
21 %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y)
26 define i8 @umax_known_bits(i8 %x, i8 %y) {
27 ; CHECK-LABEL: @umax_known_bits(
28 ; CHECK-NEXT: ret i8 -128
31 %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y)
36 define i8 @smin_known_bits(i8 %x, i8 %y) {
37 ; CHECK-LABEL: @smin_known_bits(
38 ; CHECK-NEXT: ret i8 -128
41 %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y)
46 define i8 @smax_known_bits(i8 %x, i8 %y) {
47 ; CHECK-LABEL: @smax_known_bits(
48 ; CHECK-NEXT: ret i8 0
51 %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y)
56 define i8 @smax_sext(i5 %x, i5 %y) {
57 ; CHECK-LABEL: @smax_sext(
58 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
59 ; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8
60 ; CHECK-NEXT: ret i8 [[M]]
62 %sx = sext i5 %x to i8
63 %sy = sext i5 %y to i8
64 %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy)
70 define i8 @smin_sext(i5 %x, i5 %y) {
71 ; CHECK-LABEL: @smin_sext(
72 ; CHECK-NEXT: [[SY:%.*]] = sext i5 [[Y:%.*]] to i8
73 ; CHECK-NEXT: call void @use(i8 [[SY]])
74 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Y]])
75 ; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8
76 ; CHECK-NEXT: ret i8 [[M]]
78 %sx = sext i5 %x to i8
79 %sy = sext i5 %y to i8
80 call void @use(i8 %sy)
81 %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy)
85 ; Sext doesn't change unsigned min/max comparison of narrow values.
87 define i8 @umax_sext(i5 %x, i5 %y) {
88 ; CHECK-LABEL: @umax_sext(
89 ; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i8
90 ; CHECK-NEXT: call void @use(i8 [[SX]])
91 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X]], i5 [[Y:%.*]])
92 ; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8
93 ; CHECK-NEXT: ret i8 [[M]]
95 %sx = sext i5 %x to i8
96 call void @use(i8 %sx)
97 %sy = sext i5 %y to i8
98 %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy)
102 define <3 x i8> @umin_sext(<3 x i5> %x, <3 x i5> %y) {
103 ; CHECK-LABEL: @umin_sext(
104 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> [[Y:%.*]])
105 ; CHECK-NEXT: [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
106 ; CHECK-NEXT: ret <3 x i8> [[M]]
108 %sx = sext <3 x i5> %x to <3 x i8>
109 %sy = sext <3 x i5> %y to <3 x i8>
110 %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
114 ; Negative test - zext may change sign of inputs
116 define i8 @smax_zext(i5 %x, i5 %y) {
117 ; CHECK-LABEL: @smax_zext(
118 ; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
119 ; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
120 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]])
121 ; CHECK-NEXT: ret i8 [[M]]
123 %zx = zext i5 %x to i8
124 %zy = zext i5 %y to i8
125 %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy)
129 ; Negative test - zext may change sign of inputs
131 define i8 @smin_zext(i5 %x, i5 %y) {
132 ; CHECK-LABEL: @smin_zext(
133 ; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
134 ; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
135 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]])
136 ; CHECK-NEXT: ret i8 [[M]]
138 %zx = zext i5 %x to i8
139 %zy = zext i5 %y to i8
140 %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy)
144 define i8 @umax_zext(i5 %x, i5 %y) {
145 ; CHECK-LABEL: @umax_zext(
146 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
147 ; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8
148 ; CHECK-NEXT: ret i8 [[M]]
150 %zx = zext i5 %x to i8
151 %zy = zext i5 %y to i8
152 %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy)
156 define i8 @umin_zext(i5 %x, i5 %y) {
157 ; CHECK-LABEL: @umin_zext(
158 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Y:%.*]])
159 ; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8
160 ; CHECK-NEXT: ret i8 [[M]]
162 %zx = zext i5 %x to i8
163 %zy = zext i5 %y to i8
164 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
168 ; Negative test - mismatched types
170 define i8 @umin_zext_types(i6 %x, i5 %y) {
171 ; CHECK-LABEL: @umin_zext_types(
172 ; CHECK-NEXT: [[ZX:%.*]] = zext i6 [[X:%.*]] to i8
173 ; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
174 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
175 ; CHECK-NEXT: ret i8 [[M]]
177 %zx = zext i6 %x to i8
178 %zy = zext i5 %y to i8
179 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
183 ; Negative test - mismatched extends
185 define i8 @umin_ext(i5 %x, i5 %y) {
186 ; CHECK-LABEL: @umin_ext(
187 ; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i8
188 ; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
189 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]])
190 ; CHECK-NEXT: ret i8 [[M]]
192 %sx = sext i5 %x to i8
193 %zy = zext i5 %y to i8
194 %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy)
198 ; Negative test - too many uses.
200 define i8 @umin_zext_uses(i5 %x, i5 %y) {
201 ; CHECK-LABEL: @umin_zext_uses(
202 ; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8
203 ; CHECK-NEXT: call void @use(i8 [[ZX]])
204 ; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8
205 ; CHECK-NEXT: call void @use(i8 [[ZY]])
206 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])
207 ; CHECK-NEXT: ret i8 [[M]]
209 %zx = zext i5 %x to i8
210 call void @use(i8 %zx)
211 %zy = zext i5 %y to i8
212 call void @use(i8 %zy)
213 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)
217 define i8 @smax_sext_constant(i5 %x) {
218 ; CHECK-LABEL: @smax_sext_constant(
219 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
220 ; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
221 ; CHECK-NEXT: ret i8 [[M]]
223 %e = sext i5 %x to i8
224 %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
230 define i8 @smax_sext_constant_big(i5 %x) {
231 ; CHECK-LABEL: @smax_sext_constant_big(
232 ; CHECK-NEXT: ret i8 16
234 %e = sext i5 %x to i8
235 %m = call i8 @llvm.smax.i8(i8 %e, i8 16)
241 define i8 @smax_zext_constant(i5 %x) {
242 ; CHECK-LABEL: @smax_zext_constant(
243 ; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
244 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
245 ; CHECK-NEXT: ret i8 [[M]]
247 %e = zext i5 %x to i8
248 %m = call i8 @llvm.smax.i8(i8 %e, i8 7)
252 define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
253 ; CHECK-LABEL: @smin_sext_constant(
254 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
255 ; CHECK-NEXT: [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
256 ; CHECK-NEXT: ret <3 x i8> [[M]]
258 %e = sext <3 x i5> %x to <3 x i8>
259 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>)
265 define i8 @smin_zext_constant(i5 %x) {
266 ; CHECK-LABEL: @smin_zext_constant(
267 ; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
268 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7)
269 ; CHECK-NEXT: ret i8 [[M]]
271 %e = zext i5 %x to i8
272 %m = call i8 @llvm.smin.i8(i8 %e, i8 7)
276 define i8 @umax_sext_constant(i5 %x) {
277 ; CHECK-LABEL: @umax_sext_constant(
278 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
279 ; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8
280 ; CHECK-NEXT: ret i8 [[M]]
282 %e = sext i5 %x to i8
283 %m = call i8 @llvm.umax.i8(i8 %e, i8 7)
289 define i8 @umax_sext_constant_big(i5 %x) {
290 ; CHECK-LABEL: @umax_sext_constant_big(
291 ; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
292 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126)
293 ; CHECK-NEXT: ret i8 [[M]]
295 %e = sext i5 %x to i8
296 %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
300 define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
301 ; CHECK-LABEL: @umax_zext_constant(
302 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
303 ; CHECK-NEXT: [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
304 ; CHECK-NEXT: ret <3 x i8> [[M]]
306 %e = zext <3 x i5> %x to <3 x i8>
307 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>)
313 define i8 @umax_zext_constant_big(i5 %x) {
314 ; CHECK-LABEL: @umax_zext_constant_big(
315 ; CHECK-NEXT: ret i8 126
317 %e = zext i5 %x to i8
318 %m = call i8 @llvm.umax.i8(i8 %e, i8 126)
322 define i8 @umin_sext_constant(i5 %x) {
323 ; CHECK-LABEL: @umin_sext_constant(
324 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
325 ; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
326 ; CHECK-NEXT: ret i8 [[M]]
328 %e = sext i5 %x to i8
329 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
335 define i8 @umin_sext_constant_big(i5 %x) {
336 ; CHECK-LABEL: @umin_sext_constant_big(
337 ; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
338 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126)
339 ; CHECK-NEXT: ret i8 [[M]]
341 %e = sext i5 %x to i8
342 %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
346 define i8 @umin_zext_constant(i5 %x) {
347 ; CHECK-LABEL: @umin_zext_constant(
348 ; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
349 ; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8
350 ; CHECK-NEXT: ret i8 [[M]]
352 %e = zext i5 %x to i8
353 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
359 define i8 @umin_zext_constant_big(i5 %x) {
360 ; CHECK-LABEL: @umin_zext_constant_big(
361 ; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
362 ; CHECK-NEXT: ret i8 [[E]]
364 %e = zext i5 %x to i8
365 %m = call i8 @llvm.umin.i8(i8 %e, i8 126)
371 define i8 @umin_zext_constant_uses(i5 %x) {
372 ; CHECK-LABEL: @umin_zext_constant_uses(
373 ; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
374 ; CHECK-NEXT: call void @use(i8 [[E]])
375 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
376 ; CHECK-NEXT: ret i8 [[M]]
378 %e = zext i5 %x to i8
379 call void @use(i8 %e)
380 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)
384 define i8 @smax_of_nots(i8 %x, i8 %y) {
385 ; CHECK-LABEL: @smax_of_nots(
386 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
387 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
388 ; CHECK-NEXT: ret i8 [[M]]
390 %notx = xor i8 %x, -1
391 %noty = xor i8 %y, -1
392 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
396 ; Vectors are ok (including poison lanes of not ops)
398 define <3 x i8> @smin_of_nots(<3 x i8> %x, <3 x i8> %y) {
399 ; CHECK-LABEL: @smin_of_nots(
400 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
401 ; CHECK-NEXT: [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1)
402 ; CHECK-NEXT: ret <3 x i8> [[M]]
404 %notx = xor <3 x i8> %x, <i8 -1, i8 poison, i8 -1>
405 %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 poison>
406 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty)
410 ; An extra use is ok.
412 define i8 @umax_of_nots(i8 %x, i8 %y) {
413 ; CHECK-LABEL: @umax_of_nots(
414 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
415 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
416 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]])
417 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
418 ; CHECK-NEXT: ret i8 [[M]]
420 %notx = xor i8 %x, -1
421 call void @use(i8 %notx)
422 %noty = xor i8 %y, -1
423 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty)
427 ; An extra use is ok.
429 define i8 @umin_of_nots(i8 %x, i8 %y) {
430 ; CHECK-LABEL: @umin_of_nots(
431 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
432 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
433 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y]])
434 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
435 ; CHECK-NEXT: ret i8 [[M]]
437 %notx = xor i8 %x, -1
438 %noty = xor i8 %y, -1
439 call void @use(i8 %noty)
440 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
444 ; Negative test - too many uses
446 define i8 @umin_of_nots_uses(i8 %x, i8 %y) {
447 ; CHECK-LABEL: @umin_of_nots_uses(
448 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
449 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
450 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
451 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
452 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[NOTY]])
453 ; CHECK-NEXT: ret i8 [[M]]
455 %notx = xor i8 %x, -1
456 call void @use(i8 %notx)
457 %noty = xor i8 %y, -1
458 call void @use(i8 %noty)
459 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)
463 ; Canonicalize 'not' after min/max.
465 define i8 @smax_of_not_and_const(i8 %x) {
466 ; CHECK-LABEL: @smax_of_not_and_const(
467 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -43)
468 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
469 ; CHECK-NEXT: ret i8 [[M]]
471 %notx = xor i8 %x, -1
472 %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)
476 ; Vectors are ok (including poison lanes of not ops and min/max constant operand)
478 define <3 x i8> @smin_of_not_and_const(<3 x i8> %x) {
479 ; CHECK-LABEL: @smin_of_not_and_const(
480 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -43, i8 poison, i8 -44>)
481 ; CHECK-NEXT: [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1)
482 ; CHECK-NEXT: ret <3 x i8> [[M]]
484 %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 poison>
485 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 poison, i8 43>, <3 x i8> %notx)
489 define i8 @umax_of_not_and_const(i8 %x) {
490 ; CHECK-LABEL: @umax_of_not_and_const(
491 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -45)
492 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
493 ; CHECK-NEXT: ret i8 [[M]]
495 %notx = xor i8 %x, -1
496 %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)
500 define i8 @umin_of_not_and_const(i8 %x) {
501 ; CHECK-LABEL: @umin_of_not_and_const(
502 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 44)
503 ; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
504 ; CHECK-NEXT: ret i8 [[M]]
506 %notx = xor i8 %x, -1
507 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
511 define i8 @umin_of_not_and_smax(i8 %x, i8 %y, i8 %z) {
512 ; CHECK-LABEL: @umin_of_not_and_smax(
513 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
514 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
515 ; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
516 ; CHECK-NEXT: call void @use(i8 [[NOTZ]])
517 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[Z]])
518 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[TMP1]])
519 ; CHECK-NEXT: [[M2:%.*]] = xor i8 [[TMP2]], -1
520 ; CHECK-NEXT: ret i8 [[M2]]
522 %notx = xor i8 %x, -1
523 %noty = xor i8 %y, -1
524 call void @use(i8 %noty)
525 %notz = xor i8 %z, -1
526 call void @use(i8 %notz)
527 %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz)
528 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx)
532 define i8 @smin_of_umax_and_not(i8 %x, i8 %y, i8 %z) {
533 ; CHECK-LABEL: @smin_of_umax_and_not(
534 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
535 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
536 ; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1
537 ; CHECK-NEXT: call void @use(i8 [[NOTZ]])
538 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
539 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[TMP1]])
540 ; CHECK-NEXT: [[M2:%.*]] = xor i8 [[TMP2]], -1
541 ; CHECK-NEXT: ret i8 [[M2]]
543 %notx = xor i8 %x, -1
544 %noty = xor i8 %y, -1
545 call void @use(i8 %noty)
546 %notz = xor i8 %z, -1
547 call void @use(i8 %notz)
548 %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz)
549 %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1)
553 ; Negative test - don't infinite loop on constant expression
555 define i8 @umin_of_not_and_nontrivial_const(i8 %x) {
556 ; CHECK-LABEL: @umin_of_not_and_nontrivial_const(
557 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
558 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8))
559 ; CHECK-NEXT: ret i8 [[M]]
561 %notx = xor i8 %x, -1
562 %m = call i8 @llvm.umin.i8(i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8), i8 %notx)
566 ; Negative test - too many uses
568 define i8 @umin_of_not_and_const_uses(i8 %x) {
569 ; CHECK-LABEL: @umin_of_not_and_const_uses(
570 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
571 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
572 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45)
573 ; CHECK-NEXT: ret i8 [[M]]
575 %notx = xor i8 %x, -1
576 call void @use(i8 %notx)
577 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)
581 define i8 @not_smax_of_nots(i8 %x, i8 %y) {
582 ; CHECK-LABEL: @not_smax_of_nots(
583 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
584 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
585 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
586 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
587 ; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
588 ; CHECK-NEXT: ret i8 [[NOTM]]
590 %notx = xor i8 %x, -1
591 call void @use(i8 %notx)
592 %noty = xor i8 %y, -1
593 call void @use(i8 %noty)
594 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)
595 %notm = xor i8 %m, -1
599 define i8 @not_smin_of_nots(i8 %x, i8 %y) {
600 ; CHECK-LABEL: @not_smin_of_nots(
601 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
602 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
603 ; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1
604 ; CHECK-NEXT: call void @use(i8 [[NOTY]])
605 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]])
606 ; CHECK-NEXT: call void @use(i8 [[M]])
607 ; CHECK-NEXT: [[NOTM:%.*]] = xor i8 [[M]], -1
608 ; CHECK-NEXT: ret i8 [[NOTM]]
610 %notx = xor i8 %x, -1
611 call void @use(i8 %notx)
612 %noty = xor i8 %y, -1
613 call void @use(i8 %noty)
614 %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty)
615 call void @use(i8 %m)
616 %notm = xor i8 %m, -1
620 define i8 @not_umax_of_not(i8 %x, i8 %y) {
621 ; CHECK-LABEL: @not_umax_of_not(
622 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
623 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
624 ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
625 ; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])
626 ; CHECK-NEXT: ret i8 [[NOTM]]
628 %notx = xor i8 %x, -1
629 call void @use(i8 %notx)
630 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)
631 %notm = xor i8 %m, -1
635 ; Negative test - this would require an extra instruction.
637 define i8 @not_umin_of_not(i8 %x, i8 %y) {
638 ; CHECK-LABEL: @not_umin_of_not(
639 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
640 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
641 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]])
642 ; CHECK-NEXT: call void @use(i8 [[M]])
643 ; CHECK-NEXT: [[NOTM:%.*]] = xor i8 [[M]], -1
644 ; CHECK-NEXT: ret i8 [[NOTM]]
646 %notx = xor i8 %x, -1
647 call void @use(i8 %notx)
648 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y)
649 call void @use(i8 %m)
650 %notm = xor i8 %m, -1
654 define i8 @not_umin_of_not_constant_op(i8 %x) {
655 ; CHECK-LABEL: @not_umin_of_not_constant_op(
656 ; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
657 ; CHECK-NEXT: call void @use(i8 [[NOTX]])
658 ; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43)
659 ; CHECK-NEXT: ret i8 [[NOTM]]
661 %notx = xor i8 %x, -1
662 call void @use(i8 %notx)
663 %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)
664 %notm = xor i8 %m, -1
668 define i8 @smax_negation(i8 %x, i8 %y) {
669 ; CHECK-LABEL: @smax_negation(
670 ; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
671 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
672 ; CHECK-NEXT: ret i8 [[R]]
676 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
680 define i8 @smax_negation_nsw(i8 %x, i8 %y) {
681 ; CHECK-LABEL: @smax_negation_nsw(
682 ; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
683 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
684 ; CHECK-NEXT: ret i8 [[R]]
686 %s1 = sub nsw i8 %x, %y
687 %s2 = sub nsw i8 %y, %x
688 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
692 define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
693 ; CHECK-LABEL: @smax_negation_not_nsw(
694 ; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
695 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
696 ; CHECK-NEXT: ret i8 [[R]]
698 %s1 = sub nsw i8 %x, %y
699 %s2 = sub nuw i8 %y, %x
700 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
704 define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
705 ; CHECK-LABEL: @smax_negation_vec(
706 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
707 ; CHECK-NEXT: ret <3 x i8> [[R]]
709 %s = sub <3 x i8> <i8 0, i8 poison, i8 0>, %x
710 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
714 define i8 @smin_negation(i8 %x, i8 %y) {
715 ; CHECK-LABEL: @smin_negation(
716 ; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
717 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
718 ; CHECK-NEXT: [[NABS:%.*]] = sub i8 0, [[TMP1]]
719 ; CHECK-NEXT: ret i8 [[NABS]]
723 %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)
727 define i8 @umax_negation(i8 %x, i8 %y) {
728 ; CHECK-LABEL: @umax_negation(
729 ; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
730 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
731 ; CHECK-NEXT: [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
732 ; CHECK-NEXT: ret i8 [[NABS]]
734 %s1 = sub nsw i8 %x, %y
735 %s2 = sub nsw i8 %y, %x
736 %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)
740 define i8 @umin_negation(i8 %x) {
741 ; CHECK-LABEL: @umin_negation(
742 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
743 ; CHECK-NEXT: ret i8 [[R]]
745 %s = sub nsw i8 0, %x
746 %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
750 define i8 @smax_negation_uses(i8 %x, i8 %y) {
751 ; CHECK-LABEL: @smax_negation_uses(
752 ; CHECK-NEXT: [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
753 ; CHECK-NEXT: call void @use(i8 [[S2]])
754 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false)
755 ; CHECK-NEXT: ret i8 [[R]]
759 call void @use(i8 %s2)
760 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)
764 define i8 @clamp_two_vals_smax_smin(i8 %x) {
765 ; CHECK-LABEL: @clamp_two_vals_smax_smin(
766 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43
767 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
768 ; CHECK-NEXT: ret i8 [[R]]
770 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
771 %r = call i8 @llvm.smin.i8(i8 %m, i8 43)
775 define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) {
776 ; CHECK-LABEL: @clamp_two_vals_smin_smax(
777 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], splat (i8 41)
778 ; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> splat (i8 42), <3 x i8> splat (i8 41)
779 ; CHECK-NEXT: ret <3 x i8> [[R]]
781 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)
782 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)
786 define i8 @clamp_two_vals_umax_umin(i8 %x) {
787 ; CHECK-LABEL: @clamp_two_vals_umax_umin(
788 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43
789 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43
790 ; CHECK-NEXT: ret i8 [[R]]
792 %m = call i8 @llvm.umax.i8(i8 %x, i8 42)
793 %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
797 define i8 @clamp_two_vals_umin_umax(i8 %x) {
798 ; CHECK-LABEL: @clamp_two_vals_umin_umax(
799 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41
800 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41
801 ; CHECK-NEXT: ret i8 [[R]]
803 %m = call i8 @llvm.umin.i8(i8 %x, i8 42)
804 %r = call i8 @llvm.umax.i8(i8 %m, i8 41)
808 ; Negative test - mismatched signs
810 define i8 @clamp_two_vals_smax_umin(i8 %x) {
811 ; CHECK-LABEL: @clamp_two_vals_smax_umin(
812 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
813 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43)
814 ; CHECK-NEXT: ret i8 [[R]]
816 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
817 %r = call i8 @llvm.umin.i8(i8 %m, i8 43)
821 ; Negative test - wrong range
823 define i8 @clamp_three_vals_smax_smin(i8 %x) {
824 ; CHECK-LABEL: @clamp_three_vals_smax_smin(
825 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42)
826 ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44)
827 ; CHECK-NEXT: ret i8 [[R]]
829 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)
830 %r = call i8 @llvm.smin.i8(i8 %m, i8 44)
834 ; Edge cases are simplified
836 define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {
837 ; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(
838 ; CHECK-NEXT: ret i8 0
840 %m = call i8 @llvm.umax.i8(i8 %x, i8 255)
841 %r = call i8 @llvm.umin.i8(i8 %m, i8 0)
845 ; Edge cases are simplified
847 define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {
848 ; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(
849 ; CHECK-NEXT: ret i8 -1
851 %m = call i8 @llvm.umin.i8(i8 %x, i8 0)
852 %r = call i8 @llvm.umax.i8(i8 %m, i8 255)
856 ; Edge cases are simplified
858 define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {
859 ; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(
860 ; CHECK-NEXT: ret i8 -128
862 %m = call i8 @llvm.smax.i8(i8 %x, i8 127)
863 %r = call i8 @llvm.smin.i8(i8 %m, i8 128)
867 ; Edge cases are simplified
869 define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {
870 ; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(
871 ; CHECK-NEXT: ret i8 127
873 %m = call i8 @llvm.smin.i8(i8 %x, i8 128)
874 %r = call i8 @llvm.smax.i8(i8 %m, i8 127)
879 define i8 @umin_non_zero_idiom1(i8 %a) {
880 ; CHECK-LABEL: @umin_non_zero_idiom1(
881 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
882 ; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
883 ; CHECK-NEXT: ret i8 [[RES]]
885 %res = call i8 @llvm.umin.i8(i8 %a, i8 1)
889 define i8 @umin_non_zero_idiom2(i8 %a) {
890 ; CHECK-LABEL: @umin_non_zero_idiom2(
891 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
892 ; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8
893 ; CHECK-NEXT: ret i8 [[RES]]
895 %res = call i8 @llvm.umin.i8(i8 1, i8 %a)
899 define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) {
900 ; CHECK-LABEL: @umin_non_zero_idiom3(
901 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
902 ; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
903 ; CHECK-NEXT: ret <3 x i8> [[RES]]
905 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)
909 define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) {
910 ; CHECK-LABEL: @umin_non_zero_idiom4(
911 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer
912 ; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>
913 ; CHECK-NEXT: ret <3 x i8> [[RES]]
915 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 poison, i8 poison>)
919 define i1 @umin_eq_zero(i8 %a, i8 %b) {
920 ; CHECK-LABEL: @umin_eq_zero(
921 ; CHECK-NEXT: [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
922 ; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[UMIN]], 0
923 ; CHECK-NEXT: ret i1 [[RES]]
925 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
926 %res = icmp eq i8 %umin, 0
930 define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) {
931 ; CHECK-LABEL: @umin_eq_zero2(
932 ; CHECK-NEXT: [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
933 ; CHECK-NEXT: [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer
934 ; CHECK-NEXT: ret <3 x i1> [[RES]]
937 %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
938 %res = icmp eq <3 x i8> %umin, zeroinitializer
942 define i1 @umin_ne_zero(i8 %a, i8 %b) {
943 ; CHECK-LABEL: @umin_ne_zero(
944 ; CHECK-NEXT: [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]])
945 ; CHECK-NEXT: [[RES:%.*]] = icmp ne i8 [[UMIN]], 0
946 ; CHECK-NEXT: ret i1 [[RES]]
948 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)
949 %res = icmp ne i8 %umin, 0
953 define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) {
954 ; CHECK-LABEL: @umin_ne_zero2(
955 ; CHECK-NEXT: [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]])
956 ; CHECK-NEXT: [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer
957 ; CHECK-NEXT: ret <3 x i1> [[RES]]
960 %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b)
961 %res = icmp ne <3 x i8> %umin, zeroinitializer
965 define i8 @smax(i8 %x, i8 %y, i8 %z) {
966 ; CHECK-LABEL: @smax(
967 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]])
968 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]])
969 ; CHECK-NEXT: ret i8 [[M3]]
971 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
972 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
973 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
977 define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
978 ; CHECK-LABEL: @smin(
979 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]])
980 ; CHECK-NEXT: [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]])
981 ; CHECK-NEXT: ret <3 x i8> [[M3]]
983 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)
984 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)
985 %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)
989 define i8 @umax(i8 %x, i8 %y, i8 %z) {
990 ; CHECK-LABEL: @umax(
991 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
992 ; CHECK-NEXT: call void @use(i8 [[M1]])
993 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]])
994 ; CHECK-NEXT: ret i8 [[M3]]
996 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
997 call void @use(i8 %m1)
998 %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)
999 %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)
1003 define i8 @umin(i8 %x, i8 %y, i8 %z) {
1004 ; CHECK-LABEL: @umin(
1005 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]])
1006 ; CHECK-NEXT: call void @use(i8 [[M2]])
1007 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]])
1008 ; CHECK-NEXT: ret i8 [[M3]]
1010 %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
1011 %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)
1012 call void @use(i8 %m2)
1013 %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)
1017 ; negative test - too many uses
1019 define i8 @smax_uses(i8 %x, i8 %y, i8 %z) {
1020 ; CHECK-LABEL: @smax_uses(
1021 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1022 ; CHECK-NEXT: call void @use(i8 [[M1]])
1023 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]])
1024 ; CHECK-NEXT: call void @use(i8 [[M2]])
1025 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1026 ; CHECK-NEXT: ret i8 [[M3]]
1028 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1029 call void @use(i8 %m1)
1030 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)
1031 call void @use(i8 %m2)
1032 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1036 ; negative test - must have common operand
1038 define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) {
1039 ; CHECK-LABEL: @smax_no_common_op(
1040 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1041 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]])
1042 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
1043 ; CHECK-NEXT: ret i8 [[M3]]
1045 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
1046 %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)
1047 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)
1051 define i8 @umax_demand_lshr(i8 %x) {
1052 ; CHECK-LABEL: @umax_demand_lshr(
1053 ; CHECK-NEXT: [[R:%.*]] = lshr i8 [[X:%.*]], 4
1054 ; CHECK-NEXT: ret i8 [[R]]
1056 %m = call i8 @llvm.umax.i8(i8 %x, i8 15)
1061 define i8 @umax_demand_and(i8 %x) {
1062 ; CHECK-LABEL: @umax_demand_and(
1063 ; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 10
1064 ; CHECK-NEXT: ret i8 [[R]]
1066 %m = call i8 @llvm.umax.i8(i8 1, i8 %x)
1071 define i8 @umin_demand_or_31_30(i8 %x) {
1072 ; CHECK-LABEL: @umin_demand_or_31_30(
1073 ; CHECK-NEXT: [[R:%.*]] = or i8 [[X:%.*]], 31
1074 ; CHECK-NEXT: ret i8 [[R]]
1076 %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)
1081 define i8 @umin_demand_and_7_8(i8 %x) {
1082 ; CHECK-LABEL: @umin_demand_and_7_8(
1083 ; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], -8
1084 ; CHECK-NEXT: ret i8 [[R]]
1086 %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)
1091 define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) {
1092 ; CHECK-LABEL: @neg_neg_nsw_smax(
1093 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
1094 ; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1095 ; CHECK-NEXT: ret i8 [[M]]
1097 %nx = sub nsw i8 0, %x
1098 %ny = sub nsw i8 0, %y
1099 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1103 define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) {
1104 ; CHECK-LABEL: @neg_neg_nsw_smin(
1105 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
1106 ; CHECK-NEXT: [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]]
1107 ; CHECK-NEXT: ret <3 x i8> [[M]]
1109 %nx = sub nsw <3 x i8> zeroinitializer, %x
1110 %ny = sub nsw <3 x i8> zeroinitializer, %y
1111 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)
1115 define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) {
1116 ; CHECK-LABEL: @neg_neg_nsw_smax_use0(
1117 ; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1118 ; CHECK-NEXT: call void @use(i8 [[NX]])
1119 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]])
1120 ; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1121 ; CHECK-NEXT: ret i8 [[M]]
1123 %nx = sub nsw i8 0, %x
1124 call void @use(i8 %nx)
1125 %ny = sub nsw i8 0, %y
1126 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1130 define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) {
1131 ; CHECK-LABEL: @neg_neg_nsw_smin_use1(
1132 ; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1133 ; CHECK-NEXT: call void @use(i8 [[NY]])
1134 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]])
1135 ; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]]
1136 ; CHECK-NEXT: ret i8 [[M]]
1138 %nx = sub nsw i8 0, %x
1139 %ny = sub nsw i8 0, %y
1140 call void @use(i8 %ny)
1141 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1145 ; negative test - too many uses
1147 define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) {
1148 ; CHECK-LABEL: @neg_neg_nsw_smin_use2(
1149 ; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1150 ; CHECK-NEXT: call void @use(i8 [[NX]])
1151 ; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1152 ; CHECK-NEXT: call void @use(i8 [[NY]])
1153 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1154 ; CHECK-NEXT: ret i8 [[M]]
1156 %nx = sub nsw i8 0, %x
1157 call void @use(i8 %nx)
1158 %ny = sub nsw i8 0, %y
1159 call void @use(i8 %ny)
1160 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1164 ; negative test - need nsw on both ops
1166 define i8 @neg_neg_smax(i8 %x, i8 %y) {
1167 ; CHECK-LABEL: @neg_neg_smax(
1168 ; CHECK-NEXT: [[NX:%.*]] = sub i8 0, [[X:%.*]]
1169 ; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1170 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]])
1171 ; CHECK-NEXT: ret i8 [[M]]
1174 %ny = sub nsw i8 0, %y
1175 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)
1179 ; negative test - need nsw on both ops
1181 define i8 @neg_neg_smin(i8 %x, i8 %y) {
1182 ; CHECK-LABEL: @neg_neg_smin(
1183 ; CHECK-NEXT: [[NX:%.*]] = sub i8 0, [[X:%.*]]
1184 ; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1185 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]])
1186 ; CHECK-NEXT: ret i8 [[M]]
1189 %ny = sub nsw i8 0, %y
1190 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
1194 ; negative test - need signed min/max
1196 define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) {
1197 ; CHECK-LABEL: @neg_neg_nsw_umin(
1198 ; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]]
1199 ; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]]
1200 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
1201 ; CHECK-NEXT: ret i8 [[M]]
1203 %nx = sub nsw i8 0, %x
1204 %ny = sub nsw i8 0, %y
1205 %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
1209 define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {
1210 ; CHECK-LABEL: @freeToInvertSub(
1211 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1212 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1213 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1214 ; CHECK-NEXT: call void @use(i8 [[NX]])
1215 ; CHECK-NEXT: call void @use(i8 [[NY]])
1216 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1217 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1218 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[TMP1]], [[Z]]
1219 ; CHECK-NEXT: ret i8 [[SUB]]
1224 call void @use(i8 %nx)
1225 call void @use(i8 %ny)
1226 call void @use(i8 %nz)
1227 %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1228 %sub = sub i8 %nz, %m
1232 define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {
1233 ; CHECK-LABEL: @freeToInvertSub_uses(
1234 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1235 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1236 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1237 ; CHECK-NEXT: call void @use(i8 [[NX]])
1238 ; CHECK-NEXT: call void @use(i8 [[NY]])
1239 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1240 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1241 ; CHECK-NEXT: call void @use(i8 [[M]])
1242 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[NZ]], [[M]]
1243 ; CHECK-NEXT: ret i8 [[SUB]]
1248 call void @use(i8 %nx)
1249 call void @use(i8 %ny)
1250 call void @use(i8 %nz)
1251 %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1252 call void @use(i8 %m)
1253 %sub = sub i8 %nz, %m
1257 define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {
1258 ; CHECK-LABEL: @freeToInvert(
1259 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1260 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1261 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1262 ; CHECK-NEXT: call void @use(i8 [[NX]])
1263 ; CHECK-NEXT: call void @use(i8 [[NY]])
1264 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1265 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1266 ; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1267 ; CHECK-NEXT: ret i8 [[NOT]]
1272 call void @use(i8 %nx)
1273 call void @use(i8 %ny)
1274 call void @use(i8 %nz)
1275 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1276 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1277 %not = xor i8 %m2, -1
1281 define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {
1282 ; CHECK-LABEL: @freeToInvert_use1(
1283 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1284 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1285 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1286 ; CHECK-NEXT: call void @use(i8 [[NX]])
1287 ; CHECK-NEXT: call void @use(i8 [[NY]])
1288 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1289 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1290 ; CHECK-NEXT: call void @use(i8 [[M1]])
1291 ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M1]], -1
1292 ; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])
1293 ; CHECK-NEXT: ret i8 [[NOT]]
1298 call void @use(i8 %nx)
1299 call void @use(i8 %ny)
1300 call void @use(i8 %nz)
1301 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1302 call void @use(i8 %m1)
1303 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1304 %not = xor i8 %m2, -1
1308 define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {
1309 ; CHECK-LABEL: @freeToInvert_use2(
1310 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1311 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1312 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1313 ; CHECK-NEXT: call void @use(i8 [[NX]])
1314 ; CHECK-NEXT: call void @use(i8 [[NY]])
1315 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1316 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1317 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1318 ; CHECK-NEXT: call void @use(i8 [[M2]])
1319 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M2]], -1
1320 ; CHECK-NEXT: ret i8 [[NOT]]
1325 call void @use(i8 %nx)
1326 call void @use(i8 %ny)
1327 call void @use(i8 %nz)
1328 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1329 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1330 call void @use(i8 %m2)
1331 %not = xor i8 %m2, -1
1335 define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {
1336 ; CHECK-LABEL: @freeToInvert_use3(
1337 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1338 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1339 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1340 ; CHECK-NEXT: call void @use(i8 [[NX]])
1341 ; CHECK-NEXT: call void @use(i8 [[NY]])
1342 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1343 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1344 ; CHECK-NEXT: call void @use(i8 [[M1]])
1345 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]])
1346 ; CHECK-NEXT: call void @use(i8 [[M2]])
1347 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M2]], -1
1348 ; CHECK-NEXT: ret i8 [[NOT]]
1353 call void @use(i8 %nx)
1354 call void @use(i8 %ny)
1355 call void @use(i8 %nz)
1356 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1357 call void @use(i8 %m1)
1358 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz)
1359 call void @use(i8 %m2)
1360 %not = xor i8 %m2, -1
1364 define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) {
1365 ; CHECK-LABEL: @freeToInvert_two_minmax_ops(
1366 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1367 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1368 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1369 ; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1
1370 ; CHECK-NEXT: call void @use(i8 [[NX]])
1371 ; CHECK-NEXT: call void @use(i8 [[NY]])
1372 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1373 ; CHECK-NEXT: call void @use(i8 [[NW]])
1374 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
1375 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]])
1376 ; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]])
1377 ; CHECK-NEXT: ret i8 [[NOT]]
1383 call void @use(i8 %nx)
1384 call void @use(i8 %ny)
1385 call void @use(i8 %nz)
1386 call void @use(i8 %nw)
1387 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1388 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1389 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1390 %not = xor i8 %m3, -1
1394 define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) {
1395 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1(
1396 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1397 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1398 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1399 ; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1
1400 ; CHECK-NEXT: call void @use(i8 [[NX]])
1401 ; CHECK-NEXT: call void @use(i8 [[NY]])
1402 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1403 ; CHECK-NEXT: call void @use(i8 [[NW]])
1404 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1405 ; CHECK-NEXT: call void @use(i8 [[M1]])
1406 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1407 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1408 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1
1409 ; CHECK-NEXT: ret i8 [[NOT]]
1415 call void @use(i8 %nx)
1416 call void @use(i8 %ny)
1417 call void @use(i8 %nz)
1418 call void @use(i8 %nw)
1419 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1420 call void @use(i8 %m1)
1421 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1422 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1423 %not = xor i8 %m3, -1
1427 define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) {
1428 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2(
1429 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1430 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1431 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1432 ; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1
1433 ; CHECK-NEXT: call void @use(i8 [[NX]])
1434 ; CHECK-NEXT: call void @use(i8 [[NY]])
1435 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1436 ; CHECK-NEXT: call void @use(i8 [[NW]])
1437 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1438 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1439 ; CHECK-NEXT: call void @use(i8 [[M2]])
1440 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1441 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1
1442 ; CHECK-NEXT: ret i8 [[NOT]]
1448 call void @use(i8 %nx)
1449 call void @use(i8 %ny)
1450 call void @use(i8 %nz)
1451 call void @use(i8 %nw)
1452 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1453 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1454 call void @use(i8 %m2)
1455 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1456 %not = xor i8 %m3, -1
1460 define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
1461 ; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3(
1462 ; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
1463 ; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1
1464 ; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1
1465 ; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1
1466 ; CHECK-NEXT: call void @use(i8 [[NX]])
1467 ; CHECK-NEXT: call void @use(i8 [[NY]])
1468 ; CHECK-NEXT: call void @use(i8 [[NZ]])
1469 ; CHECK-NEXT: call void @use(i8 [[NW]])
1470 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]])
1471 ; CHECK-NEXT: call void @use(i8 [[M1]])
1472 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]])
1473 ; CHECK-NEXT: call void @use(i8 [[M2]])
1474 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
1475 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1
1476 ; CHECK-NEXT: ret i8 [[NOT]]
1482 call void @use(i8 %nx)
1483 call void @use(i8 %ny)
1484 call void @use(i8 %nz)
1485 call void @use(i8 %nw)
1486 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny)
1487 call void @use(i8 %m1)
1488 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz)
1489 call void @use(i8 %m2)
1490 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2)
1491 %not = xor i8 %m3, -1
1495 define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) {
1496 ; CHECK-LABEL: @sub_not_min_max(
1497 ; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1498 ; CHECK-NEXT: call void @use(i8 [[NOTG]])
1499 ; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1500 ; CHECK-NEXT: call void @use(i8 [[NOTB]])
1501 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G]])
1502 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1503 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1504 ; CHECK-NEXT: ret i8 [[CK]]
1506 %notr = xor i8 %r, -1
1507 %notg = xor i8 %g, -1
1508 call void @use(i8 %notg)
1509 %notb = xor i8 %b, -1
1510 call void @use(i8 %notb)
1511 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1512 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1513 %ck = sub i8 %notr, %k
1517 define i8 @sub_not_min_max_uses1(i8 %r, i8 %g, i8 %b) {
1518 ; CHECK-LABEL: @sub_not_min_max_uses1(
1519 ; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1520 ; CHECK-NEXT: call void @use(i8 [[NOTR]])
1521 ; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1522 ; CHECK-NEXT: call void @use(i8 [[NOTG]])
1523 ; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1524 ; CHECK-NEXT: call void @use(i8 [[NOTB]])
1525 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R]], i8 [[G]])
1526 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1527 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1528 ; CHECK-NEXT: ret i8 [[CK]]
1530 %notr = xor i8 %r, -1
1531 call void @use(i8 %notr)
1532 %notg = xor i8 %g, -1
1533 call void @use(i8 %notg)
1534 %notb = xor i8 %b, -1
1535 call void @use(i8 %notb)
1536 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1537 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1538 %ck = sub i8 %notr, %k
1542 define i8 @sub_not_min_max_uses2(i8 %r, i8 %g, i8 %b) {
1543 ; CHECK-LABEL: @sub_not_min_max_uses2(
1544 ; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
1545 ; CHECK-NEXT: call void @use(i8 [[NOTR]])
1546 ; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
1547 ; CHECK-NEXT: call void @use(i8 [[NOTG]])
1548 ; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
1549 ; CHECK-NEXT: call void @use(i8 [[NOTB]])
1550 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1551 ; CHECK-NEXT: call void @use(i8 [[M]])
1552 ; CHECK-NEXT: [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1553 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1554 ; CHECK-NEXT: ret i8 [[CK]]
1556 %notr = xor i8 %r, -1
1557 call void @use(i8 %notr)
1558 %notg = xor i8 %g, -1
1559 call void @use(i8 %notg)
1560 %notb = xor i8 %b, -1
1561 call void @use(i8 %notb)
1562 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1563 call void @use(i8 %m)
1564 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1565 %ck = sub i8 %notr, %k
1569 declare void @use4(i8, i8, i8, i8)
1571 define void @cmyk(i8 %r, i8 %g, i8 %b) {
1572 ; CHECK-LABEL: @cmyk(
1573 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1574 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1575 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1576 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1577 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1578 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1579 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1580 ; CHECK-NEXT: ret void
1582 %notr = xor i8 %r, -1
1583 %notg = xor i8 %g, -1
1584 %notb = xor i8 %b, -1
1585 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1586 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1587 %ck = sub i8 %notr, %k
1588 %mk = sub i8 %notg, %k
1589 %yk = sub i8 %notb, %k
1590 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1594 ; Same as above, but flip the operands of %k.
1596 define void @cmyk_commute1(i8 %r, i8 %g, i8 %b) {
1597 ; CHECK-LABEL: @cmyk_commute1(
1598 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1599 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1600 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1601 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1602 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1603 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1604 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1605 ; CHECK-NEXT: ret void
1607 %notr = xor i8 %r, -1
1608 %notg = xor i8 %g, -1
1609 %notb = xor i8 %b, -1
1610 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1611 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1612 %ck = sub i8 %notr, %k
1613 %mk = sub i8 %notg, %k
1614 %yk = sub i8 %notb, %k
1615 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1619 ; Same as above, but also flip the operands of %m.
1621 define void @cmyk_commute2(i8 %r, i8 %g, i8 %b) {
1622 ; CHECK-LABEL: @cmyk_commute2(
1623 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1624 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1625 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1626 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1627 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1628 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1629 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1630 ; CHECK-NEXT: ret void
1632 %notr = xor i8 %r, -1
1633 %notg = xor i8 %g, -1
1634 %notb = xor i8 %b, -1
1635 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1636 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1637 %ck = sub i8 %notr, %k
1638 %mk = sub i8 %notg, %k
1639 %yk = sub i8 %notb, %k
1640 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1644 ; Same as original, but only flip the operands of %m.
1646 define void @cmyk_commute3(i8 %r, i8 %g, i8 %b) {
1647 ; CHECK-LABEL: @cmyk_commute3(
1648 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1649 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1650 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1651 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1652 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1653 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1654 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1655 ; CHECK-NEXT: ret void
1657 %notr = xor i8 %r, -1
1658 %notg = xor i8 %g, -1
1659 %notb = xor i8 %b, -1
1660 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1661 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1662 %ck = sub i8 %notr, %k
1663 %mk = sub i8 %notg, %k
1664 %yk = sub i8 %notb, %k
1665 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1669 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1670 ; Also verify that we don't need matching min/max ops.
1672 define void @cmyk_commute4(i8 %r, i8 %g, i8 %b) {
1673 ; CHECK-LABEL: @cmyk_commute4(
1674 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1675 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1676 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1677 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1678 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1679 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1680 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1681 ; CHECK-NEXT: ret void
1683 %notr = xor i8 %r, -1
1684 %notg = xor i8 %g, -1
1685 %notb = xor i8 %b, -1
1686 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1687 %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1688 %yk = sub i8 %notb, %k
1689 %ck = sub i8 %notr, %k
1690 %mk = sub i8 %notg, %k
1691 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1695 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1696 ; Also verify that we don't need matching min/max ops.
1698 define void @cmyk_commute5(i8 %r, i8 %g, i8 %b) {
1699 ; CHECK-LABEL: @cmyk_commute5(
1700 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1701 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1702 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1703 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1704 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1705 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1706 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1707 ; CHECK-NEXT: ret void
1709 %notr = xor i8 %r, -1
1710 %notg = xor i8 %g, -1
1711 %notb = xor i8 %b, -1
1712 %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1713 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1714 %ck = sub i8 %notr, %k
1715 %yk = sub i8 %notb, %k
1716 %mk = sub i8 %notg, %k
1717 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1721 define void @cmyk_commute6(i8 %r, i8 %g, i8 %b) {
1722 ; CHECK-LABEL: @cmyk_commute6(
1723 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1724 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1725 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1726 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1727 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1728 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1729 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1730 ; CHECK-NEXT: ret void
1732 %notr = xor i8 %r, -1
1733 %notg = xor i8 %g, -1
1734 %notb = xor i8 %b, -1
1735 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1736 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1737 %ck = sub i8 %k, %notr
1738 %mk = sub i8 %k, %notg
1739 %yk = sub i8 %k, %notb
1740 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1744 ; Same as above, but flip the operands of %k.
1746 define void @cmyk_commute7(i8 %r, i8 %g, i8 %b) {
1747 ; CHECK-LABEL: @cmyk_commute7(
1748 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]])
1749 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1750 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1751 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1752 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1753 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1754 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1755 ; CHECK-NEXT: ret void
1757 %notr = xor i8 %r, -1
1758 %notg = xor i8 %g, -1
1759 %notb = xor i8 %b, -1
1760 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg)
1761 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1762 %ck = sub i8 %k, %notr
1763 %mk = sub i8 %k, %notg
1764 %yk = sub i8 %k, %notb
1765 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1769 ; Same as above, but also flip the operands of %m.
1771 define void @cmyk_commute8(i8 %r, i8 %g, i8 %b) {
1772 ; CHECK-LABEL: @cmyk_commute8(
1773 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1774 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1775 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1776 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1777 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1778 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1779 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1780 ; CHECK-NEXT: ret void
1782 %notr = xor i8 %r, -1
1783 %notg = xor i8 %g, -1
1784 %notb = xor i8 %b, -1
1785 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1786 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m)
1787 %ck = sub i8 %k, %notr
1788 %mk = sub i8 %k, %notg
1789 %yk = sub i8 %k, %notb
1790 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1794 ; Same as original, but only flip the operands of %m.
1796 define void @cmyk_commute9(i8 %r, i8 %g, i8 %b) {
1797 ; CHECK-LABEL: @cmyk_commute9(
1798 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1799 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1800 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1801 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1802 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1803 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1804 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1805 ; CHECK-NEXT: ret void
1807 %notr = xor i8 %r, -1
1808 %notg = xor i8 %g, -1
1809 %notb = xor i8 %b, -1
1810 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1811 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1812 %ck = sub i8 %k, %notr
1813 %mk = sub i8 %k, %notg
1814 %yk = sub i8 %k, %notb
1815 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1819 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1820 ; Also verify that we don't need matching min/max ops.
1822 define void @cmyk_commute10(i8 %r, i8 %g, i8 %b) {
1823 ; CHECK-LABEL: @cmyk_commute10(
1824 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1825 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1826 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1827 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]]
1828 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]]
1829 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]]
1830 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1831 ; CHECK-NEXT: ret void
1833 %notr = xor i8 %r, -1
1834 %notg = xor i8 %g, -1
1835 %notb = xor i8 %b, -1
1836 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr)
1837 %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb)
1838 %yk = sub i8 %notb, %k
1839 %ck = sub i8 %k, %notr
1840 %mk = sub i8 %notg, %k
1841 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1845 ; Not exactly a commute, but make sure order of folds doesn't change anything.
1846 ; Also verify that we don't need matching min/max ops.
1848 define void @cmyk_commute11(i8 %r, i8 %g, i8 %b) {
1849 ; CHECK-LABEL: @cmyk_commute11(
1850 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]])
1851 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]])
1852 ; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1
1853 ; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
1854 ; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]]
1855 ; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]]
1856 ; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
1857 ; CHECK-NEXT: ret void
1859 %notr = xor i8 %r, -1
1860 %notg = xor i8 %g, -1
1861 %notb = xor i8 %b, -1
1862 %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr)
1863 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb)
1864 %ck = sub i8 %notr, %k
1865 %yk = sub i8 %k, %notb
1866 %mk = sub i8 %k, %notg
1867 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)
1871 define i8 @smax_offset(i8 %x) {
1872 ; CHECK-LABEL: @smax_offset(
1873 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -127)
1874 ; CHECK-NEXT: [[M:%.*]] = add nsw i8 [[TMP1]], 3
1875 ; CHECK-NEXT: ret i8 [[M]]
1877 %a = add nsw i8 %x, 3
1878 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1882 ; This is handled by InstSimplify; testing here to confirm assert.
1884 define i8 @smax_offset_limit(i8 %x) {
1885 ; CHECK-LABEL: @smax_offset_limit(
1886 ; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1887 ; CHECK-NEXT: ret i8 [[A]]
1889 %a = add nsw i8 %x, 3
1890 %m = call i8 @llvm.smax.i8(i8 %a, i8 -125)
1894 ; This is handled by InstSimplify; testing here to confirm assert.
1896 define i8 @smax_offset_overflow(i8 %x) {
1897 ; CHECK-LABEL: @smax_offset_overflow(
1898 ; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1899 ; CHECK-NEXT: ret i8 [[A]]
1901 %a = add nsw i8 %x, 3
1902 %m = call i8 @llvm.smax.i8(i8 %a, i8 -126)
1906 ; negative test - require nsw
1908 define i8 @smax_offset_may_wrap(i8 %x) {
1909 ; CHECK-LABEL: @smax_offset_may_wrap(
1910 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 3
1911 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1912 ; CHECK-NEXT: ret i8 [[M]]
1915 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1921 define i8 @smax_offset_uses(i8 %x) {
1922 ; CHECK-LABEL: @smax_offset_uses(
1923 ; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3
1924 ; CHECK-NEXT: call void @use(i8 [[A]])
1925 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)
1926 ; CHECK-NEXT: ret i8 [[M]]
1928 %a = add nsw i8 %x, 3
1929 call void @use(i8 %a)
1930 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)
1934 define <3 x i8> @smin_offset(<3 x i8> %x) {
1935 ; CHECK-LABEL: @smin_offset(
1936 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 -127))
1937 ; CHECK-NEXT: [[M:%.*]] = or disjoint <3 x i8> [[TMP1]], splat (i8 124)
1938 ; CHECK-NEXT: ret <3 x i8> [[M]]
1940 %a = add nsw nuw <3 x i8> %x, <i8 124, i8 124, i8 124>
1941 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %a, <3 x i8> <i8 -3, i8 -3, i8 -3>)
1945 ; This is handled by InstSimplify; testing here to confirm assert.
1947 define i8 @smin_offset_limit(i8 %x) {
1948 ; CHECK-LABEL: @smin_offset_limit(
1949 ; CHECK-NEXT: ret i8 -3
1951 %a = add nsw i8 %x, 125
1952 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1956 ; This is handled by InstSimplify; testing here to confirm assert.
1958 define i8 @smin_offset_overflow(i8 %x) {
1959 ; CHECK-LABEL: @smin_offset_overflow(
1960 ; CHECK-NEXT: ret i8 -3
1962 %a = add nsw i8 %x, 126
1963 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1967 ; negative test - require nsw
1969 define i8 @smin_offset_may_wrap(i8 %x) {
1970 ; CHECK-LABEL: @smin_offset_may_wrap(
1971 ; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 124
1972 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1973 ; CHECK-NEXT: ret i8 [[M]]
1975 %a = add nuw i8 %x, 124
1976 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1982 define i8 @smin_offset_uses(i8 %x) {
1983 ; CHECK-LABEL: @smin_offset_uses(
1984 ; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 124
1985 ; CHECK-NEXT: call void @use(i8 [[A]])
1986 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)
1987 ; CHECK-NEXT: ret i8 [[M]]
1989 %a = add nsw i8 %x, 124
1990 call void @use(i8 %a)
1991 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)
1995 ; Note: 'nsw' must not propagate here.
1997 define <3 x i8> @umax_offset(<3 x i8> %x) {
1998 ; CHECK-LABEL: @umax_offset(
1999 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 3))
2000 ; CHECK-NEXT: [[M:%.*]] = add nuw <3 x i8> [[TMP1]], splat (i8 127)
2001 ; CHECK-NEXT: ret <3 x i8> [[M]]
2003 %a = add nsw nuw <3 x i8> %x, <i8 127, i8 127, i8 127>
2004 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 130, i8 130, i8 130>)
2008 ; This is handled by InstSimplify; testing here to confirm assert.
2010 define i8 @umax_offset_limit(i8 %x) {
2011 ; CHECK-LABEL: @umax_offset_limit(
2012 ; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2013 ; CHECK-NEXT: ret i8 [[A]]
2015 %a = add nuw i8 %x, 3
2016 %m = call i8 @llvm.umax.i8(i8 %a, i8 3)
2020 ; This is handled by InstSimplify; testing here to confirm assert.
2022 define i8 @umax_offset_overflow(i8 %x) {
2023 ; CHECK-LABEL: @umax_offset_overflow(
2024 ; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2025 ; CHECK-NEXT: ret i8 [[A]]
2027 %a = add nuw i8 %x, 3
2028 %m = call i8 @llvm.umax.i8(i8 %a, i8 2)
2032 ; negative test - require nuw
2034 define i8 @umax_offset_may_wrap(i8 %x) {
2035 ; CHECK-LABEL: @umax_offset_may_wrap(
2036 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 3
2037 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2038 ; CHECK-NEXT: ret i8 [[M]]
2041 %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2047 define i8 @umax_offset_uses(i8 %x) {
2048 ; CHECK-LABEL: @umax_offset_uses(
2049 ; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3
2050 ; CHECK-NEXT: call void @use(i8 [[A]])
2051 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)
2052 ; CHECK-NEXT: ret i8 [[M]]
2054 %a = add nuw i8 %x, 3
2055 call void @use(i8 %a)
2056 %m = call i8 @llvm.umax.i8(i8 %a, i8 4)
2060 define i8 @umin_offset(i8 %x) {
2061 ; CHECK-LABEL: @umin_offset(
2062 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[X:%.*]], 0
2063 ; CHECK-NEXT: [[M:%.*]] = select i1 [[DOTNOT]], i8 -5, i8 -4
2064 ; CHECK-NEXT: ret i8 [[M]]
2066 %a = add nuw i8 %x, 251
2067 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2071 ; This is handled by InstSimplify; testing here to confirm assert.
2073 define i8 @umin_offset_limit(i8 %x) {
2074 ; CHECK-LABEL: @umin_offset_limit(
2075 ; CHECK-NEXT: ret i8 -4
2077 %a = add nuw i8 %x, 252
2078 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2082 ; This is handled by InstSimplify; testing here to confirm assert.
2084 define i8 @umin_offset_overflow(i8 %x) {
2085 ; CHECK-LABEL: @umin_offset_overflow(
2086 ; CHECK-NEXT: ret i8 -4
2088 %a = add nuw i8 %x, 253
2089 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2093 ; negative test - require nuw
2095 define i8 @umin_offset_may_wrap(i8 %x) {
2096 ; CHECK-LABEL: @umin_offset_may_wrap(
2097 ; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], -5
2098 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2099 ; CHECK-NEXT: ret i8 [[M]]
2101 %a = add nsw i8 %x, 251
2102 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2108 define i8 @umin_offset_uses(i8 %x) {
2109 ; CHECK-LABEL: @umin_offset_uses(
2110 ; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], -5
2111 ; CHECK-NEXT: call void @use(i8 [[A]])
2112 ; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)
2113 ; CHECK-NEXT: ret i8 [[M]]
2115 %a = add nuw i8 %x, 251
2116 call void @use(i8 %a)
2117 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)
2121 ; TODO: This could transform
2123 define <3 x i8> @umax_vector_splat_poison(<3 x i8> %x) {
2124 ; CHECK-LABEL: @umax_vector_splat_poison(
2125 ; CHECK-NEXT: [[A:%.*]] = add nuw <3 x i8> [[X:%.*]], <i8 poison, i8 64, i8 64>
2126 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[A]], <3 x i8> <i8 13, i8 -126, i8 -126>)
2127 ; CHECK-NEXT: ret <3 x i8> [[R]]
2129 %a = add nuw <3 x i8> %x, <i8 poison, i8 64, i8 64>
2130 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 13, i8 130, i8 130>)
2134 ; Issue #52884 - this would assert because of a failure to simplify.
2136 define i8 @smax_offset_simplify(i8 %x) {
2137 ; CHECK-LABEL: @smax_offset_simplify(
2138 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[X:%.*]], 50
2139 ; CHECK-NEXT: ret i8 [[TMP1]]
2141 %1 = add nuw nsw i8 50, %x
2142 %m = call i8 @llvm.smax.i8(i8 %1, i8 -124)
2146 define <3 x i8> @smax_smax_reassoc_constants(<3 x i8> %x) {
2147 ; CHECK-LABEL: @smax_smax_reassoc_constants(
2148 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 43, i8 44>)
2149 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2151 %m1 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)
2152 %m2 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2156 define i8 @smin_smin_reassoc_constants(i8 %x) {
2157 ; CHECK-LABEL: @smin_smin_reassoc_constants(
2158 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -3)
2159 ; CHECK-NEXT: ret i8 [[M2]]
2161 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)
2162 %m2 = call i8 @llvm.smin.i8(i8 -3, i8 %m1)
2166 define <3 x i8> @umax_umax_reassoc_constants(<3 x i8> %x) {
2167 ; CHECK-LABEL: @umax_umax_reassoc_constants(
2168 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 -113, i8 poison>)
2169 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2171 %m1 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)
2172 %m2 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 143, i8 poison>)
2178 define i8 @umin_umin_reassoc_constants(i8 %x) {
2179 ; CHECK-LABEL: @umin_umin_reassoc_constants(
2180 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -116)
2181 ; CHECK-NEXT: call void @use(i8 [[M1]])
2182 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
2183 ; CHECK-NEXT: ret i8 [[M2]]
2185 %m1 = call i8 @llvm.umin.i8(i8 140, i8 %x)
2186 call void @use(i8 %m1)
2187 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)
2191 ; negative test - must have matching intrinsics
2193 define i8 @smin_smax_reassoc_constants(i8 %x) {
2194 ; CHECK-LABEL: @smin_smax_reassoc_constants(
2195 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 97)
2196 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 -3)
2197 ; CHECK-NEXT: ret i8 [[M2]]
2199 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)
2200 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 -3)
2204 define i8 @smax_smax_reassoc_constant(i8 %x, i8 %y) {
2205 ; CHECK-LABEL: @smax_smax_reassoc_constant(
2206 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2207 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42)
2208 ; CHECK-NEXT: ret i8 [[M2]]
2210 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
2211 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 42)
2215 define <3 x i8> @smin_smin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) {
2216 ; CHECK-LABEL: @smin_smin_reassoc_constant(
2217 ; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2218 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2219 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2221 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %y)
2222 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2226 define i8 @umax_umax_reassoc_constant(i8 %x, i8 %y) {
2227 ; CHECK-LABEL: @umax_umax_reassoc_constant(
2228 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2229 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2230 ; CHECK-NEXT: ret i8 [[M2]]
2232 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
2233 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 42)
2237 define <3 x i8> @umin_umin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) {
2238 ; CHECK-LABEL: @umin_umin_reassoc_constant(
2239 ; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2240 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2241 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2243 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> %y)
2244 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)
2248 define i8 @umin_umin_reassoc_constant_use(i8 %x, i8 %y) {
2249 ; CHECK-LABEL: @umin_umin_reassoc_constant_use(
2250 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2251 ; CHECK-NEXT: call void @use(i8 [[M1]])
2252 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 42)
2253 ; CHECK-NEXT: ret i8 [[M2]]
2255 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
2256 call void @use(i8 %m1)
2257 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)
2261 define i8 @smax_smax_reassoc_constant_sink(i8 %x, i8 %y) {
2262 ; CHECK-LABEL: @smax_smax_reassoc_constant_sink(
2263 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2264 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42)
2265 ; CHECK-NEXT: ret i8 [[M2]]
2267 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2268 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)
2272 define <3 x i8> @smin_smin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) {
2273 ; CHECK-LABEL: @smin_smin_reassoc_constant_sink(
2274 ; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2275 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2276 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2278 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)
2279 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %y)
2283 define i8 @umax_umax_reassoc_constant_sink(i8 %x, i8 %y) {
2284 ; CHECK-LABEL: @umax_umax_reassoc_constant_sink(
2285 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2286 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2287 ; CHECK-NEXT: ret i8 [[M2]]
2289 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)
2290 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 %y)
2294 define <3 x i8> @umin_umin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) {
2295 ; CHECK-LABEL: @umin_umin_reassoc_constant_sink(
2296 ; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2297 ; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>)
2298 ; CHECK-NEXT: ret <3 x i8> [[M2]]
2300 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)
2301 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> %y)
2305 define i8 @umin_umin_reassoc_constant_sink_use(i8 %x, i8 %y) {
2306 ; CHECK-LABEL: @umin_umin_reassoc_constant_sink_use(
2307 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 42)
2308 ; CHECK-NEXT: call void @use(i8 [[M1]])
2309 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[Y:%.*]])
2310 ; CHECK-NEXT: ret i8 [[M2]]
2312 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 42)
2313 call void @use(i8 %m1)
2314 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %y)
2318 define i8 @smax_smax_smax_reassoc_constants(i8 %x, i8 %y) {
2319 ; CHECK-LABEL: @smax_smax_smax_reassoc_constants(
2320 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2321 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126)
2322 ; CHECK-NEXT: ret i8 [[M3]]
2324 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2325 %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %m1)
2326 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)
2330 define i8 @smax_smax_smax_reassoc_constants_swap(i8 %x, i8 %y) {
2331 ; CHECK-LABEL: @smax_smax_smax_reassoc_constants_swap(
2332 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2333 ; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126)
2334 ; CHECK-NEXT: ret i8 [[M3]]
2336 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)
2337 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)
2338 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)
2342 define i8 @smin_smin_smin_reassoc_constants(i8 %x, i8 %y) {
2343 ; CHECK-LABEL: @smin_smin_smin_reassoc_constants(
2344 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
2345 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 42)
2346 ; CHECK-NEXT: ret i8 [[M2]]
2348 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 42)
2349 %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %m1)
2350 %m3 = call i8 @llvm.smin.i8(i8 %m2, i8 126)
2354 define i8 @umax_umax_reassoc_constantexpr_sink(i8 %x, i8 %y) {
2355 ; CHECK-LABEL: @umax_umax_reassoc_constantexpr_sink(
2356 ; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8))
2357 ; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42)
2358 ; CHECK-NEXT: ret i8 [[M2]]
2360 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)
2361 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8))
2365 define <3 x i8> @smax_unary_shuffle_ops(<3 x i8> %x, <3 x i8> %y) {
2366 ; CHECK-LABEL: @smax_unary_shuffle_ops(
2367 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]])
2368 ; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2369 ; CHECK-NEXT: ret <3 x i8> [[R]]
2371 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2372 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2373 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2377 define <3 x i8> @smin_unary_shuffle_ops_use_poison_mask_elt(<3 x i8> %x, <3 x i8> %y) {
2378 ; CHECK-LABEL: @smin_unary_shuffle_ops_use_poison_mask_elt(
2379 ; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2380 ; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]])
2381 ; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X]], <3 x i8> [[Y:%.*]])
2382 ; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2383 ; CHECK-NEXT: ret <3 x i8> [[R]]
2385 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2386 call void @use_vec(<3 x i8> %sx)
2387 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>
2388 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2392 define <3 x i8> @umax_unary_shuffle_ops_use_widening(<2 x i8> %x, <2 x i8> %y) {
2393 ; CHECK-LABEL: @umax_unary_shuffle_ops_use_widening(
2394 ; CHECK-NEXT: [[SY:%.*]] = shufflevector <2 x i8> [[Y:%.*]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2395 ; CHECK-NEXT: call void @use_vec(<3 x i8> [[SY]])
2396 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.umax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y]])
2397 ; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2398 ; CHECK-NEXT: ret <3 x i8> [[R]]
2400 %sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2401 %sy = shufflevector <2 x i8> %y, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>
2402 call void @use_vec(<3 x i8> %sy)
2403 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2407 define <3 x i8> @umin_unary_shuffle_ops_narrowing(<4 x i8> %x, <4 x i8> %y) {
2408 ; CHECK-LABEL: @umin_unary_shuffle_ops_narrowing(
2409 ; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.umin.v4i8(<4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]])
2410 ; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2411 ; CHECK-NEXT: ret <3 x i8> [[R]]
2413 %sx = shufflevector <4 x i8> %x, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2414 %sy = shufflevector <4 x i8> %y, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>
2415 %r = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2419 ; negative test - must have 2 shuffles
2421 define <3 x i8> @smax_unary_shuffle_ops_unshuffled_op(<3 x i8> %x, <3 x i8> %y) {
2422 ; CHECK-LABEL: @smax_unary_shuffle_ops_unshuffled_op(
2423 ; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2424 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[Y:%.*]])
2425 ; CHECK-NEXT: ret <3 x i8> [[R]]
2427 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2428 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %y)
2432 ; negative test - must have identical masks
2434 define <3 x i8> @smax_unary_shuffle_ops_wrong_mask(<3 x i8> %x, <3 x i8> %y) {
2435 ; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_mask(
2436 ; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2437 ; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2438 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2439 ; CHECK-NEXT: ret <3 x i8> [[R]]
2441 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>
2442 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2443 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2447 ; negative test - must be unary shuffles
2449 define <3 x i8> @smax_unary_shuffle_ops_wrong_shuf(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {
2450 ; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_shuf(
2451 ; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]], <3 x i32> <i32 1, i32 0, i32 3>
2452 ; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> [[Z]], <3 x i32> <i32 1, i32 0, i32 3>
2453 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2454 ; CHECK-NEXT: ret <3 x i8> [[R]]
2456 %sx = shufflevector <3 x i8> %x, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>
2457 %sy = shufflevector <3 x i8> %y, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>
2458 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2462 ; negative test - too many uses
2464 define <3 x i8> @smin_unary_shuffle_ops_uses(<3 x i8> %x, <3 x i8> %y) {
2465 ; CHECK-LABEL: @smin_unary_shuffle_ops_uses(
2466 ; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2467 ; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]])
2468 ; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2469 ; CHECK-NEXT: call void @use_vec(<3 x i8> [[SY]])
2470 ; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])
2471 ; CHECK-NEXT: ret <3 x i8> [[R]]
2473 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2474 call void @use_vec(<3 x i8> %sx)
2475 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>
2476 call void @use_vec(<3 x i8> %sy)
2477 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)
2481 ; This would assert/crash because we tried to zext to i1.
2483 @g = external dso_local global i32, align 4
2485 define i1 @PR57986() {
2486 ; CHECK-LABEL: @PR57986(
2487 ; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1)
2489 %umin = call i1 @llvm.umin.i1(i1 ptrtoint (ptr @g to i1), i1 true)
2493 define i8 @fold_umax_with_knownbits_info(i8 %a, i8 %b) {
2494 ; CHECK-LABEL: @fold_umax_with_knownbits_info(
2495 ; CHECK-NEXT: entry:
2496 ; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 1
2497 ; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 1
2498 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2499 ; CHECK-NEXT: ret i8 [[SUB]]
2504 %sub = sub i8 %a1, %a2
2505 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)
2509 define <3 x i8> @fold_umax_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {
2510 ; CHECK-LABEL: @fold_umax_with_knownbits_info_poison_in_splat(
2511 ; CHECK-NEXT: entry:
2512 ; CHECK-NEXT: [[A1:%.*]] = or <3 x i8> [[A:%.*]], splat (i8 1)
2513 ; CHECK-NEXT: [[A2:%.*]] = shl <3 x i8> [[B:%.*]], splat (i8 1)
2514 ; CHECK-NEXT: [[SUB:%.*]] = sub <3 x i8> [[A1]], [[A2]]
2515 ; CHECK-NEXT: ret <3 x i8> [[SUB]]
2518 %a1 = or <3 x i8> %a, <i8 1, i8 1, i8 1>
2519 %a2 = shl <3 x i8> %b, <i8 1, i8 1, i8 1>
2520 %sub = sub <3 x i8> %a1, %a2
2521 %val = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sub, <3 x i8> <i8 1, i8 poison, i8 1>)
2525 define i8 @fold_umin_with_knownbits_info(i8 %a, i8 %b) {
2526 ; CHECK-LABEL: @fold_umin_with_knownbits_info(
2527 ; CHECK-NEXT: entry:
2528 ; CHECK-NEXT: ret i8 3
2533 %sub = sub i8 %a1, %a2
2534 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)
2538 define <3 x i8> @fold_umin_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {
2539 ; CHECK-LABEL: @fold_umin_with_knownbits_info_poison_in_splat(
2540 ; CHECK-NEXT: entry:
2541 ; CHECK-NEXT: ret <3 x i8> splat (i8 3)
2544 %a1 = or <3 x i8> %a, <i8 3, i8 3, i8 3>
2545 %a2 = shl <3 x i8> %b, <i8 2, i8 2, i8 2>
2546 %sub = sub <3 x i8> %a1, %a2
2547 %val = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sub, <3 x i8> <i8 3, i8 poison, i8 3>)
2551 define i8 @fold_umax_with_knownbits_info_fail(i8 %a, i8 %b) {
2552 ; CHECK-LABEL: @fold_umax_with_knownbits_info_fail(
2553 ; CHECK-NEXT: entry:
2554 ; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 2
2555 ; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 1
2556 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2557 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umax.i8(i8 [[SUB]], i8 1)
2558 ; CHECK-NEXT: ret i8 [[VAL]]
2563 %sub = sub i8 %a1, %a2
2564 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)
2568 define i8 @fold_umin_with_knownbits_info_fail(i8 %a, i8 %b) {
2569 ; CHECK-LABEL: @fold_umin_with_knownbits_info_fail(
2570 ; CHECK-NEXT: entry:
2571 ; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 1
2572 ; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 2
2573 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]
2574 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umin.i8(i8 [[SUB]], i8 3)
2575 ; CHECK-NEXT: ret i8 [[VAL]]
2580 %sub = sub i8 %a1, %a2
2581 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)
2585 define i8 @test_umax_and(i8 %x, i8 %y) {
2586 ; CHECK-LABEL: @test_umax_and(
2587 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2588 ; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64
2589 ; CHECK-NEXT: ret i8 [[RES1]]
2591 %x1 = and i8 %x, -64
2592 %y1 = and i8 %y, -64
2593 %res = call i8 @llvm.umax.i8(i8 %x1, i8 %y1)
2597 define i8 @test_umin_and(i8 %x, i8 %y) {
2598 ; CHECK-LABEL: @test_umin_and(
2599 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2600 ; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64
2601 ; CHECK-NEXT: ret i8 [[RES1]]
2603 %x1 = and i8 %x, -64
2604 %y1 = and i8 %y, -64
2605 %res = call i8 @llvm.umin.i8(i8 %x1, i8 %y1)
2609 define i8 @test_smax_and(i8 %x, i8 %y) {
2610 ; CHECK-LABEL: @test_smax_and(
2611 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2612 ; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64
2613 ; CHECK-NEXT: ret i8 [[RES1]]
2615 %x1 = and i8 %x, -64
2616 %y1 = and i8 %y, -64
2617 %res = call i8 @llvm.smax.i8(i8 %x1, i8 %y1)
2621 define i8 @test_smin_and(i8 %x, i8 %y) {
2622 ; CHECK-LABEL: @test_smin_and(
2623 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])
2624 ; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64
2625 ; CHECK-NEXT: ret i8 [[RES1]]
2627 %x1 = and i8 %x, -64
2628 %y1 = and i8 %y, -64
2629 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2633 define i8 @test_smin_and_mismatch(i8 %x, i8 %y) {
2634 ; CHECK-LABEL: @test_smin_and_mismatch(
2635 ; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], -64
2636 ; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], -32
2637 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2638 ; CHECK-NEXT: ret i8 [[RES]]
2640 %x1 = and i8 %x, -64
2641 %y1 = and i8 %y, -32
2642 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2646 define i8 @test_smin_and_non_negated_pow2(i8 %x, i8 %y) {
2647 ; CHECK-LABEL: @test_smin_and_non_negated_pow2(
2648 ; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 31
2649 ; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 31
2650 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2651 ; CHECK-NEXT: ret i8 [[RES]]
2655 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)
2659 define i8 @test_smin_and_multiuse(i8 %x, i8 %y) {
2660 ; CHECK-LABEL: @test_smin_and_multiuse(
2661 ; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 31
2662 ; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 31
2663 ; CHECK-NEXT: call void @use(i8 [[Y1]])
2664 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])
2665 ; CHECK-NEXT: ret i8 [[RES]]
2669 call void @use(i8 %y1)
2670 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)