2721 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare i1 @llvm.umin.i1(i1, i1)5declare i8 @llvm.umin.i8(i8, i8)6declare i8 @llvm.umax.i8(i8, i8)7declare i8 @llvm.smin.i8(i8, i8)8declare i8 @llvm.smax.i8(i8, i8)9declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>)10declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>)11declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>)12declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>)13declare void @use(i8)14declare void @use_vec(<3 x i8>)15 16define i8 @umin_known_bits(i8 %x, i8 %y) {17; CHECK-LABEL: @umin_known_bits(18; CHECK-NEXT: ret i8 019;20 %x2 = and i8 %x, 12721 %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y)22 %r = and i8 %m, -12823 ret i8 %r24}25 26define i8 @umax_known_bits(i8 %x, i8 %y) {27; CHECK-LABEL: @umax_known_bits(28; CHECK-NEXT: ret i8 -12829;30 %x2 = or i8 %x, -12831 %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y)32 %r = and i8 %m, -12833 ret i8 %r34}35 36define i8 @smin_known_bits(i8 %x, i8 %y) {37; CHECK-LABEL: @smin_known_bits(38; CHECK-NEXT: ret i8 -12839;40 %x2 = or i8 %x, -12841 %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y)42 %r = and i8 %m, -12843 ret i8 %r44}45 46define i8 @smax_known_bits(i8 %x, i8 %y) {47; CHECK-LABEL: @smax_known_bits(48; CHECK-NEXT: ret i8 049;50 %x2 = and i8 %x, 12751 %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y)52 %r = and i8 %m, -12853 ret i8 %r54}55 56define 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 i860; CHECK-NEXT: ret i8 [[M]]61;62 %sx = sext i5 %x to i863 %sy = sext i5 %y to i864 %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy)65 ret i8 %m66}67 68; Extra use is ok.69 70define i8 @smin_sext(i5 %x, i5 %y) {71; CHECK-LABEL: @smin_sext(72; CHECK-NEXT: [[SY:%.*]] = sext i5 [[Y:%.*]] to i873; 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 i876; CHECK-NEXT: ret i8 [[M]]77;78 %sx = sext i5 %x to i879 %sy = sext i5 %y to i880 call void @use(i8 %sy)81 %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy)82 ret i8 %m83}84 85; Sext doesn't change unsigned min/max comparison of narrow values.86 87define i8 @umax_sext(i5 %x, i5 %y) {88; CHECK-LABEL: @umax_sext(89; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i890; 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 i893; CHECK-NEXT: ret i8 [[M]]94;95 %sx = sext i5 %x to i896 call void @use(i8 %sx)97 %sy = sext i5 %y to i898 %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy)99 ret i8 %m100}101 102define <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]]107;108 %sx = sext <3 x i5> %x to <3 x i8>109 %sy = sext <3 x i5> %y to <3 x i8>110 %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)111 ret <3 x i8> %m112}113 114; Negative test - zext may change sign of inputs115 116define i8 @smax_zext(i5 %x, i5 %y) {117; CHECK-LABEL: @smax_zext(118; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8119; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8120; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]])121; CHECK-NEXT: ret i8 [[M]]122;123 %zx = zext i5 %x to i8124 %zy = zext i5 %y to i8125 %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy)126 ret i8 %m127}128 129; Negative test - zext may change sign of inputs130 131define i8 @smin_zext(i5 %x, i5 %y) {132; CHECK-LABEL: @smin_zext(133; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8134; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8135; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]])136; CHECK-NEXT: ret i8 [[M]]137;138 %zx = zext i5 %x to i8139 %zy = zext i5 %y to i8140 %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy)141 ret i8 %m142}143 144define 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 i8148; CHECK-NEXT: ret i8 [[M]]149;150 %zx = zext i5 %x to i8151 %zy = zext i5 %y to i8152 %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy)153 ret i8 %m154}155 156define 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 i8160; CHECK-NEXT: ret i8 [[M]]161;162 %zx = zext i5 %x to i8163 %zy = zext i5 %y to i8164 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)165 ret i8 %m166}167 168; Negative test - mismatched types169 170define i8 @umin_zext_types(i6 %x, i5 %y) {171; CHECK-LABEL: @umin_zext_types(172; CHECK-NEXT: [[ZX:%.*]] = zext i6 [[X:%.*]] to i8173; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8174; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]])175; CHECK-NEXT: ret i8 [[M]]176;177 %zx = zext i6 %x to i8178 %zy = zext i5 %y to i8179 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)180 ret i8 %m181}182 183; Negative test - mismatched extends184 185define i8 @umin_ext(i5 %x, i5 %y) {186; CHECK-LABEL: @umin_ext(187; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i8188; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8189; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]])190; CHECK-NEXT: ret i8 [[M]]191;192 %sx = sext i5 %x to i8193 %zy = zext i5 %y to i8194 %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy)195 ret i8 %m196}197 198; Negative test - too many uses.199 200define i8 @umin_zext_uses(i5 %x, i5 %y) {201; CHECK-LABEL: @umin_zext_uses(202; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8203; CHECK-NEXT: call void @use(i8 [[ZX]])204; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8205; 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]]208;209 %zx = zext i5 %x to i8210 call void @use(i8 %zx)211 %zy = zext i5 %y to i8212 call void @use(i8 %zy)213 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy)214 ret i8 %m215}216 217define 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 i8221; CHECK-NEXT: ret i8 [[M]]222;223 %e = sext i5 %x to i8224 %m = call i8 @llvm.smax.i8(i8 %e, i8 7)225 ret i8 %m226}227 228; simplifies229 230define i8 @smax_sext_constant_big(i5 %x) {231; CHECK-LABEL: @smax_sext_constant_big(232; CHECK-NEXT: ret i8 16233;234 %e = sext i5 %x to i8235 %m = call i8 @llvm.smax.i8(i8 %e, i8 16)236 ret i8 %m237}238 239; negative test240 241define i8 @smax_zext_constant(i5 %x) {242; CHECK-LABEL: @smax_zext_constant(243; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8244; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)245; CHECK-NEXT: ret i8 [[M]]246;247 %e = zext i5 %x to i8248 %m = call i8 @llvm.smax.i8(i8 %e, i8 7)249 ret i8 %m250}251 252define <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]]257;258 %e = sext <3 x i5> %x to <3 x i8>259 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>)260 ret <3 x i8> %m261}262 263; negative test264 265define i8 @smin_zext_constant(i5 %x) {266; CHECK-LABEL: @smin_zext_constant(267; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8268; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7)269; CHECK-NEXT: ret i8 [[M]]270;271 %e = zext i5 %x to i8272 %m = call i8 @llvm.smin.i8(i8 %e, i8 7)273 ret i8 %m274}275 276define 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 i8280; CHECK-NEXT: ret i8 [[M]]281;282 %e = sext i5 %x to i8283 %m = call i8 @llvm.umax.i8(i8 %e, i8 7)284 ret i8 %m285}286 287; negative test288 289define i8 @umax_sext_constant_big(i5 %x) {290; CHECK-LABEL: @umax_sext_constant_big(291; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8292; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126)293; CHECK-NEXT: ret i8 [[M]]294;295 %e = sext i5 %x to i8296 %m = call i8 @llvm.umax.i8(i8 %e, i8 126)297 ret i8 %m298}299 300define <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]]305;306 %e = zext <3 x i5> %x to <3 x i8>307 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>)308 ret <3 x i8> %m309}310 311; simplifies312 313define i8 @umax_zext_constant_big(i5 %x) {314; CHECK-LABEL: @umax_zext_constant_big(315; CHECK-NEXT: ret i8 126316;317 %e = zext i5 %x to i8318 %m = call i8 @llvm.umax.i8(i8 %e, i8 126)319 ret i8 %m320}321 322define 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 i8326; CHECK-NEXT: ret i8 [[M]]327;328 %e = sext i5 %x to i8329 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)330 ret i8 %m331}332 333; negative test334 335define i8 @umin_sext_constant_big(i5 %x) {336; CHECK-LABEL: @umin_sext_constant_big(337; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8338; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126)339; CHECK-NEXT: ret i8 [[M]]340;341 %e = sext i5 %x to i8342 %m = call i8 @llvm.umin.i8(i8 %e, i8 126)343 ret i8 %m344}345 346define 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 i8350; CHECK-NEXT: ret i8 [[M]]351;352 %e = zext i5 %x to i8353 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)354 ret i8 %m355}356 357; simplifies358 359define i8 @umin_zext_constant_big(i5 %x) {360; CHECK-LABEL: @umin_zext_constant_big(361; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8362; CHECK-NEXT: ret i8 [[E]]363;364 %e = zext i5 %x to i8365 %m = call i8 @llvm.umin.i8(i8 %e, i8 126)366 ret i8 %m367}368 369; negative test370 371define i8 @umin_zext_constant_uses(i5 %x) {372; CHECK-LABEL: @umin_zext_constant_uses(373; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8374; 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]]377;378 %e = zext i5 %x to i8379 call void @use(i8 %e)380 %m = call i8 @llvm.umin.i8(i8 %e, i8 7)381 ret i8 %m382}383 384define 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]], -1388; CHECK-NEXT: ret i8 [[M]]389;390 %notx = xor i8 %x, -1391 %noty = xor i8 %y, -1392 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)393 ret i8 %m394}395 396; Vectors are ok (including poison lanes of not ops)397 398define <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]]403;404 %notx = xor <3 x i8> %x, <i8 -1, i8 poison, i8 -1>405 %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 poison>406 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty)407 ret <3 x i8> %m408}409 410; An extra use is ok.411 412define i8 @umax_of_nots(i8 %x, i8 %y) {413; CHECK-LABEL: @umax_of_nots(414; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1415; 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]], -1418; CHECK-NEXT: ret i8 [[M]]419;420 %notx = xor i8 %x, -1421 call void @use(i8 %notx)422 %noty = xor i8 %y, -1423 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty)424 ret i8 %m425}426 427; An extra use is ok.428 429define i8 @umin_of_nots(i8 %x, i8 %y) {430; CHECK-LABEL: @umin_of_nots(431; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1432; 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]], -1435; CHECK-NEXT: ret i8 [[M]]436;437 %notx = xor i8 %x, -1438 %noty = xor i8 %y, -1439 call void @use(i8 %noty)440 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)441 ret i8 %m442}443 444; Negative test - too many uses445 446define i8 @umin_of_nots_uses(i8 %x, i8 %y) {447; CHECK-LABEL: @umin_of_nots_uses(448; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1449; CHECK-NEXT: call void @use(i8 [[NOTX]])450; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1451; 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]]454;455 %notx = xor i8 %x, -1456 call void @use(i8 %notx)457 %noty = xor i8 %y, -1458 call void @use(i8 %noty)459 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty)460 ret i8 %m461}462 463; Canonicalize 'not' after min/max.464 465define 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]], -1469; CHECK-NEXT: ret i8 [[M]]470;471 %notx = xor i8 %x, -1472 %m = call i8 @llvm.smax.i8(i8 %notx, i8 42)473 ret i8 %m474}475 476; Vectors are ok (including poison lanes of not ops and min/max constant operand)477 478define <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]]483;484 %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 poison>485 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 poison, i8 43>, <3 x i8> %notx)486 ret <3 x i8> %m487}488 489define 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]], -1493; CHECK-NEXT: ret i8 [[M]]494;495 %notx = xor i8 %x, -1496 %m = call i8 @llvm.umax.i8(i8 %notx, i8 44)497 ret i8 %m498}499 500define 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]], -1504; CHECK-NEXT: ret i8 [[M]]505;506 %notx = xor i8 %x, -1507 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)508 ret i8 %m509}510 511define 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:%.*]], -1514; CHECK-NEXT: call void @use(i8 [[NOTY]])515; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1516; 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]], -1520; CHECK-NEXT: ret i8 [[M2]]521;522 %notx = xor i8 %x, -1523 %noty = xor i8 %y, -1524 call void @use(i8 %noty)525 %notz = xor i8 %z, -1526 call void @use(i8 %notz)527 %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz)528 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx)529 ret i8 %m2530}531 532define 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:%.*]], -1535; CHECK-NEXT: call void @use(i8 [[NOTY]])536; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1537; 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]], -1541; CHECK-NEXT: ret i8 [[M2]]542;543 %notx = xor i8 %x, -1544 %noty = xor i8 %y, -1545 call void @use(i8 %noty)546 %notz = xor i8 %z, -1547 call void @use(i8 %notz)548 %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz)549 %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1)550 ret i8 %m2551}552 553; Negative test - don't infinite loop on constant expression554 555define 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:%.*]], -1558; 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]]560;561 %notx = xor i8 %x, -1562 %m = call i8 @llvm.umin.i8(i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8), i8 %notx)563 ret i8 %m564}565 566; Negative test - too many uses567 568define 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:%.*]], -1571; 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]]574;575 %notx = xor i8 %x, -1576 call void @use(i8 %notx)577 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx)578 ret i8 %m579}580 581define i8 @not_smax_of_nots(i8 %x, i8 %y) {582; CHECK-LABEL: @not_smax_of_nots(583; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1584; CHECK-NEXT: call void @use(i8 [[NOTX]])585; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1586; 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]]589;590 %notx = xor i8 %x, -1591 call void @use(i8 %notx)592 %noty = xor i8 %y, -1593 call void @use(i8 %noty)594 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty)595 %notm = xor i8 %m, -1596 ret i8 %notm597}598 599define i8 @not_smin_of_nots(i8 %x, i8 %y) {600; CHECK-LABEL: @not_smin_of_nots(601; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1602; CHECK-NEXT: call void @use(i8 [[NOTX]])603; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1604; 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]], -1608; CHECK-NEXT: ret i8 [[NOTM]]609;610 %notx = xor i8 %x, -1611 call void @use(i8 %notx)612 %noty = xor i8 %y, -1613 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, -1617 ret i8 %notm618}619 620define i8 @not_umax_of_not(i8 %x, i8 %y) {621; CHECK-LABEL: @not_umax_of_not(622; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1623; CHECK-NEXT: call void @use(i8 [[NOTX]])624; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1625; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]])626; CHECK-NEXT: ret i8 [[NOTM]]627;628 %notx = xor i8 %x, -1629 call void @use(i8 %notx)630 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y)631 %notm = xor i8 %m, -1632 ret i8 %notm633}634 635; Negative test - this would require an extra instruction.636 637define i8 @not_umin_of_not(i8 %x, i8 %y) {638; CHECK-LABEL: @not_umin_of_not(639; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1640; 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]], -1644; CHECK-NEXT: ret i8 [[NOTM]]645;646 %notx = xor i8 %x, -1647 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, -1651 ret i8 %notm652}653 654define 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:%.*]], -1657; 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]]660;661 %notx = xor i8 %x, -1662 call void @use(i8 %notx)663 %m = call i8 @llvm.umin.i8(i8 %notx, i8 42)664 %notm = xor i8 %m, -1665 ret i8 %notm666}667 668define 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]]673;674 %s1 = sub i8 %x, %y675 %s2 = sub i8 %y, %x676 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)677 ret i8 %r678}679 680define 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]]685;686 %s1 = sub nsw i8 %x, %y687 %s2 = sub nsw i8 %y, %x688 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)689 ret i8 %r690}691 692define 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]]697;698 %s1 = sub nsw i8 %x, %y699 %s2 = sub nuw i8 %y, %x700 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)701 ret i8 %r702}703 704define <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]]708;709 %s = sub <3 x i8> <i8 0, i8 poison, i8 0>, %x710 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)711 ret <3 x i8> %r712}713 714define 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]]720;721 %s1 = sub i8 %x, %y722 %s2 = sub i8 %y, %x723 %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2)724 ret i8 %r725}726 727define 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]]733;734 %s1 = sub nsw i8 %x, %y735 %s2 = sub nsw i8 %y, %x736 %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2)737 ret i8 %r738}739 740define 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]]744;745 %s = sub nsw i8 0, %x746 %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)747 ret i8 %r748}749 750define 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]]756;757 %s1 = sub i8 %x, %y758 %s2 = sub i8 %y, %x759 call void @use(i8 %s2)760 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2)761 ret i8 %r762}763 764define i8 @clamp_two_vals_smax_smin(i8 %x) {765; CHECK-LABEL: @clamp_two_vals_smax_smin(766; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43767; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43768; CHECK-NEXT: ret i8 [[R]]769;770 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)771 %r = call i8 @llvm.smin.i8(i8 %m, i8 43)772 ret i8 %r773}774 775define <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 slt <3 x i8> [[X:%.*]], splat (i8 42)778; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> splat (i8 41), <3 x i8> splat (i8 42)779; CHECK-NEXT: ret <3 x i8> [[R]]780;781 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>)782 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>)783 ret <3 x i8> %r784}785 786define i8 @clamp_two_vals_umax_umin(i8 %x) {787; CHECK-LABEL: @clamp_two_vals_umax_umin(788; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43789; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43790; CHECK-NEXT: ret i8 [[R]]791;792 %m = call i8 @llvm.umax.i8(i8 %x, i8 42)793 %r = call i8 @llvm.umin.i8(i8 %m, i8 43)794 ret i8 %r795}796 797define i8 @clamp_two_vals_umin_umax(i8 %x) {798; CHECK-LABEL: @clamp_two_vals_umin_umax(799; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 42800; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 41, i8 42801; CHECK-NEXT: ret i8 [[R]]802;803 %m = call i8 @llvm.umin.i8(i8 %x, i8 42)804 %r = call i8 @llvm.umax.i8(i8 %m, i8 41)805 ret i8 %r806}807 808; Negative test - mismatched signs809 810define 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]]815;816 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)817 %r = call i8 @llvm.umin.i8(i8 %m, i8 43)818 ret i8 %r819}820 821; Negative test - wrong range822 823define 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]]828;829 %m = call i8 @llvm.smax.i8(i8 %x, i8 42)830 %r = call i8 @llvm.smin.i8(i8 %m, i8 44)831 ret i8 %r832}833 834; Edge cases are simplified835 836define i8 @clamp_two_vals_umax_umin_edge(i8 %x) {837; CHECK-LABEL: @clamp_two_vals_umax_umin_edge(838; CHECK-NEXT: ret i8 0839;840 %m = call i8 @llvm.umax.i8(i8 %x, i8 255)841 %r = call i8 @llvm.umin.i8(i8 %m, i8 0)842 ret i8 %r843}844 845; Edge cases are simplified846 847define i8 @clamp_two_vals_umin_umax_edge(i8 %x) {848; CHECK-LABEL: @clamp_two_vals_umin_umax_edge(849; CHECK-NEXT: ret i8 -1850;851 %m = call i8 @llvm.umin.i8(i8 %x, i8 0)852 %r = call i8 @llvm.umax.i8(i8 %m, i8 255)853 ret i8 %r854}855 856; Edge cases are simplified857 858define i8 @clamp_two_vals_smax_smin_edge(i8 %x) {859; CHECK-LABEL: @clamp_two_vals_smax_smin_edge(860; CHECK-NEXT: ret i8 -128861;862 %m = call i8 @llvm.smax.i8(i8 %x, i8 127)863 %r = call i8 @llvm.smin.i8(i8 %m, i8 128)864 ret i8 %r865}866 867; Edge cases are simplified868 869define i8 @clamp_two_vals_smin_smax_edge(i8 %x) {870; CHECK-LABEL: @clamp_two_vals_smin_smax_edge(871; CHECK-NEXT: ret i8 127872;873 %m = call i8 @llvm.smin.i8(i8 %x, i8 128)874 %r = call i8 @llvm.smax.i8(i8 %m, i8 127)875 ret i8 %r876}877 878 879define i8 @umin_non_zero_idiom1(i8 %a) {880; CHECK-LABEL: @umin_non_zero_idiom1(881; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0882; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8883; CHECK-NEXT: ret i8 [[RES]]884;885 %res = call i8 @llvm.umin.i8(i8 %a, i8 1)886 ret i8 %res887}888 889define i8 @umin_non_zero_idiom2(i8 %a) {890; CHECK-LABEL: @umin_non_zero_idiom2(891; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0892; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8893; CHECK-NEXT: ret i8 [[RES]]894;895 %res = call i8 @llvm.umin.i8(i8 1, i8 %a)896 ret i8 %res897}898 899define <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:%.*]], zeroinitializer902; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>903; CHECK-NEXT: ret <3 x i8> [[RES]]904;905 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>)906 ret <3 x i8> %res907}908 909define <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:%.*]], zeroinitializer912; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8>913; CHECK-NEXT: ret <3 x i8> [[RES]]914;915 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 poison, i8 poison>)916 ret <3 x i8> %res917}918 919define 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]], 0923; CHECK-NEXT: ret i1 [[RES]]924;925 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)926 %res = icmp eq i8 %umin, 0927 ret i1 %res928}929 930define <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]], zeroinitializer934; CHECK-NEXT: ret <3 x i1> [[RES]]935;936 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, zeroinitializer939 ret <3 x i1> %res940}941 942define 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]], 0946; CHECK-NEXT: ret i1 [[RES]]947;948 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b)949 %res = icmp ne i8 %umin, 0950 ret i1 %res951}952 953define <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]], zeroinitializer957; CHECK-NEXT: ret <3 x i1> [[RES]]958;959 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, zeroinitializer962 ret <3 x i1> %res963}964 965define 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]]970;971 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)972 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)973 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)974 ret i8 %m3975}976 977define <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]]982;983 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x)984 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z)985 %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2)986 ret <3 x i8> %m3987}988 989define 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]]995;996 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)997 call void @use(i8 %m1)998 %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x)999 %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2)1000 ret i8 %m31001}1002 1003define 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]]1009;1010 %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x)1011 %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x)1012 call void @use(i8 %m2)1013 %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2)1014 ret i8 %m31015}1016 1017; negative test - too many uses1018 1019define 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]]1027;1028 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)1029 call void @use(i8 %m1)1030 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z)1031 call void @use(i8 %m2)1032 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)1033 ret i8 %m31034}1035 1036; negative test - must have common operand1037 1038define 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]]1044;1045 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)1046 %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z)1047 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2)1048 ret i8 %m31049}1050 1051define i8 @umax_demand_lshr(i8 %x) {1052; CHECK-LABEL: @umax_demand_lshr(1053; CHECK-NEXT: [[R:%.*]] = lshr i8 [[X:%.*]], 41054; CHECK-NEXT: ret i8 [[R]]1055;1056 %m = call i8 @llvm.umax.i8(i8 %x, i8 15)1057 %r = lshr i8 %m, 41058 ret i8 %r1059}1060 1061define i8 @umax_demand_and(i8 %x) {1062; CHECK-LABEL: @umax_demand_and(1063; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 101064; CHECK-NEXT: ret i8 [[R]]1065;1066 %m = call i8 @llvm.umax.i8(i8 1, i8 %x)1067 %r = and i8 %m, 101068 ret i8 %r1069}1070 1071define i8 @umin_demand_or_31_30(i8 %x) {1072; CHECK-LABEL: @umin_demand_or_31_30(1073; CHECK-NEXT: [[R:%.*]] = or i8 [[X:%.*]], 311074; CHECK-NEXT: ret i8 [[R]]1075;1076 %m = call i8 @llvm.umin.i8(i8 -30, i8 %x)1077 %r = or i8 %m, 311078 ret i8 %r1079}1080 1081define i8 @umin_demand_and_7_8(i8 %x) {1082; CHECK-LABEL: @umin_demand_and_7_8(1083; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], -81084; CHECK-NEXT: ret i8 [[R]]1085;1086 %m = call i8 @llvm.umin.i8(i8 %x, i8 -7)1087 %r = and i8 %m, -81088 ret i8 %r1089}1090 1091define 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]]1096;1097 %nx = sub nsw i8 0, %x1098 %ny = sub nsw i8 0, %y1099 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)1100 ret i8 %m1101}1102 1103define <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]]1108;1109 %nx = sub nsw <3 x i8> zeroinitializer, %x1110 %ny = sub nsw <3 x i8> zeroinitializer, %y1111 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny)1112 ret <3 x i8> %m1113}1114 1115define 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]]1122;1123 %nx = sub nsw i8 0, %x1124 call void @use(i8 %nx)1125 %ny = sub nsw i8 0, %y1126 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)1127 ret i8 %m1128}1129 1130define 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]]1137;1138 %nx = sub nsw i8 0, %x1139 %ny = sub nsw i8 0, %y1140 call void @use(i8 %ny)1141 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)1142 ret i8 %m1143}1144 1145; negative test - too many uses1146 1147define 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]]1155;1156 %nx = sub nsw i8 0, %x1157 call void @use(i8 %nx)1158 %ny = sub nsw i8 0, %y1159 call void @use(i8 %ny)1160 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)1161 ret i8 %m1162}1163 1164; negative test - need nsw on both ops1165 1166define 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]]1172;1173 %nx = sub i8 0, %x1174 %ny = sub nsw i8 0, %y1175 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny)1176 ret i8 %m1177}1178 1179; negative test - need nsw on both ops1180 1181define 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]]1187;1188 %nx = sub i8 0, %x1189 %ny = sub nsw i8 0, %y1190 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)1191 ret i8 %m1192}1193 1194; negative test - need signed min/max1195 1196define 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]]1202;1203 %nx = sub nsw i8 0, %x1204 %ny = sub nsw i8 0, %y1205 %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)1206 ret i8 %m1207}1208 1209define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) {1210; CHECK-LABEL: @freeToInvertSub(1211; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11212; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11213; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11214; 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]]1220;1221 %nx = xor i8 %x, -11222 %ny = xor i8 %y, -11223 %nz = xor i8 %z, -11224 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, %m1229 ret i8 %sub1230}1231 1232define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) {1233; CHECK-LABEL: @freeToInvertSub_uses(1234; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11235; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11236; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11237; 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]]1244;1245 %nx = xor i8 %x, -11246 %ny = xor i8 %y, -11247 %nz = xor i8 %z, -11248 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, %m1254 ret i8 %sub1255}1256 1257define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) {1258; CHECK-LABEL: @freeToInvert(1259; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11260; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11261; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11262; 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]]1268;1269 %nx = xor i8 %x, -11270 %ny = xor i8 %y, -11271 %nz = xor i8 %z, -11272 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, -11278 ret i8 %not1279}1280 1281define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) {1282; CHECK-LABEL: @freeToInvert_use1(1283; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11284; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11285; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11286; 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]], -11292; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]])1293; CHECK-NEXT: ret i8 [[NOT]]1294;1295 %nx = xor i8 %x, -11296 %ny = xor i8 %y, -11297 %nz = xor i8 %z, -11298 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, -11305 ret i8 %not1306}1307 1308define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) {1309; CHECK-LABEL: @freeToInvert_use2(1310; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11311; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11312; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11313; 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]], -11320; CHECK-NEXT: ret i8 [[NOT]]1321;1322 %nx = xor i8 %x, -11323 %ny = xor i8 %y, -11324 %nz = xor i8 %z, -11325 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, -11332 ret i8 %not1333}1334 1335define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) {1336; CHECK-LABEL: @freeToInvert_use3(1337; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -11338; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11339; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11340; 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]], -11348; CHECK-NEXT: ret i8 [[NOT]]1349;1350 %nx = xor i8 %x, -11351 %ny = xor i8 %y, -11352 %nz = xor i8 %z, -11353 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, -11361 ret i8 %not1362}1363 1364define 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:%.*]], -11367; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11368; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11369; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -11370; 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]]1378;1379 %nx = xor i8 %x, -11380 %ny = xor i8 %y, -11381 %nz = xor i8 %z, -11382 %nw = xor i8 %w, -11383 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, -11391 ret i8 %not1392}1393 1394define 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:%.*]], -11397; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11398; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11399; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -11400; 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]], -11409; CHECK-NEXT: ret i8 [[NOT]]1410;1411 %nx = xor i8 %x, -11412 %ny = xor i8 %y, -11413 %nz = xor i8 %z, -11414 %nw = xor i8 %w, -11415 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, -11424 ret i8 %not1425}1426 1427define 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:%.*]], -11430; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11431; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11432; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -11433; 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]], -11442; CHECK-NEXT: ret i8 [[NOT]]1443;1444 %nx = xor i8 %x, -11445 %ny = xor i8 %y, -11446 %nz = xor i8 %z, -11447 %nw = xor i8 %w, -11448 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, -11457 ret i8 %not1458}1459 1460define 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:%.*]], -11463; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -11464; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -11465; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -11466; 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]], -11476; CHECK-NEXT: ret i8 [[NOT]]1477;1478 %nx = xor i8 %x, -11479 %ny = xor i8 %y, -11480 %nz = xor i8 %z, -11481 %nw = xor i8 %w, -11482 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, -11492 ret i8 %not1493}1494 1495define 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:%.*]], -11498; CHECK-NEXT: call void @use(i8 [[NOTG]])1499; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -11500; 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]]1505;1506 %notr = xor i8 %r, -11507 %notg = xor i8 %g, -11508 call void @use(i8 %notg)1509 %notb = xor i8 %b, -11510 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, %k1514 ret i8 %ck1515}1516 1517define 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:%.*]], -11520; CHECK-NEXT: call void @use(i8 [[NOTR]])1521; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -11522; CHECK-NEXT: call void @use(i8 [[NOTG]])1523; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -11524; 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]]1529;1530 %notr = xor i8 %r, -11531 call void @use(i8 %notr)1532 %notg = xor i8 %g, -11533 call void @use(i8 %notg)1534 %notb = xor i8 %b, -11535 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, %k1539 ret i8 %ck1540}1541 1542define 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:%.*]], -11545; CHECK-NEXT: call void @use(i8 [[NOTR]])1546; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -11547; CHECK-NEXT: call void @use(i8 [[NOTG]])1548; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -11549; 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]]1555;1556 %notr = xor i8 %r, -11557 call void @use(i8 %notr)1558 %notg = xor i8 %g, -11559 call void @use(i8 %notg)1560 %notb = xor i8 %b, -11561 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, %k1566 ret i8 %ck1567}1568 1569declare void @use4(i8, i8, i8, i8)1570 1571define 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]], -11576; 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 void1581;1582 %notr = xor i8 %r, -11583 %notg = xor i8 %g, -11584 %notb = xor i8 %b, -11585 %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, %k1588 %mk = sub i8 %notg, %k1589 %yk = sub i8 %notb, %k1590 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1591 ret void1592}1593 1594; Same as above, but flip the operands of %k.1595 1596define 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]], -11601; 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 void1606;1607 %notr = xor i8 %r, -11608 %notg = xor i8 %g, -11609 %notb = xor i8 %b, -11610 %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, %k1613 %mk = sub i8 %notg, %k1614 %yk = sub i8 %notb, %k1615 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1616 ret void1617}1618 1619; Same as above, but also flip the operands of %m.1620 1621define 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]], -11626; 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 void1631;1632 %notr = xor i8 %r, -11633 %notg = xor i8 %g, -11634 %notb = xor i8 %b, -11635 %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, %k1638 %mk = sub i8 %notg, %k1639 %yk = sub i8 %notb, %k1640 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1641 ret void1642}1643 1644; Same as original, but only flip the operands of %m.1645 1646define 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]], -11651; 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 void1656;1657 %notr = xor i8 %r, -11658 %notg = xor i8 %g, -11659 %notb = xor i8 %b, -11660 %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, %k1663 %mk = sub i8 %notg, %k1664 %yk = sub i8 %notb, %k1665 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1666 ret void1667}1668 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.1671 1672define 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]], -11677; 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 void1682;1683 %notr = xor i8 %r, -11684 %notg = xor i8 %g, -11685 %notb = xor i8 %b, -11686 %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, %k1689 %ck = sub i8 %notr, %k1690 %mk = sub i8 %notg, %k1691 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1692 ret void1693}1694 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.1697 1698define 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]], -11703; 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 void1708;1709 %notr = xor i8 %r, -11710 %notg = xor i8 %g, -11711 %notb = xor i8 %b, -11712 %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, %k1715 %yk = sub i8 %notb, %k1716 %mk = sub i8 %notg, %k1717 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1718 ret void1719}1720 1721define 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]], -11726; 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 void1731;1732 %notr = xor i8 %r, -11733 %notg = xor i8 %g, -11734 %notb = xor i8 %b, -11735 %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, %notr1738 %mk = sub i8 %k, %notg1739 %yk = sub i8 %k, %notb1740 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1741 ret void1742}1743 1744; Same as above, but flip the operands of %k.1745 1746define 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]], -11751; 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 void1756;1757 %notr = xor i8 %r, -11758 %notg = xor i8 %g, -11759 %notb = xor i8 %b, -11760 %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, %notr1763 %mk = sub i8 %k, %notg1764 %yk = sub i8 %k, %notb1765 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1766 ret void1767}1768 1769; Same as above, but also flip the operands of %m.1770 1771define 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]], -11776; 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 void1781;1782 %notr = xor i8 %r, -11783 %notg = xor i8 %g, -11784 %notb = xor i8 %b, -11785 %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, %notr1788 %mk = sub i8 %k, %notg1789 %yk = sub i8 %k, %notb1790 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1791 ret void1792}1793 1794; Same as original, but only flip the operands of %m.1795 1796define 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]], -11801; 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 void1806;1807 %notr = xor i8 %r, -11808 %notg = xor i8 %g, -11809 %notb = xor i8 %b, -11810 %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, %notr1813 %mk = sub i8 %k, %notg1814 %yk = sub i8 %k, %notb1815 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1816 ret void1817}1818 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.1821 1822define 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]], -11827; 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 void1832;1833 %notr = xor i8 %r, -11834 %notg = xor i8 %g, -11835 %notb = xor i8 %b, -11836 %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, %k1839 %ck = sub i8 %k, %notr1840 %mk = sub i8 %notg, %k1841 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1842 ret void1843}1844 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.1847 1848define 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]], -11853; 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 void1858;1859 %notr = xor i8 %r, -11860 %notg = xor i8 %g, -11861 %notb = xor i8 %b, -11862 %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, %k1865 %yk = sub i8 %k, %notb1866 %mk = sub i8 %k, %notg1867 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k)1868 ret void1869}1870 1871define 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]], 31875; CHECK-NEXT: ret i8 [[M]]1876;1877 %a = add nsw i8 %x, 31878 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)1879 ret i8 %m1880}1881 1882; This is handled by InstSimplify; testing here to confirm assert.1883 1884define i8 @smax_offset_limit(i8 %x) {1885; CHECK-LABEL: @smax_offset_limit(1886; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 31887; CHECK-NEXT: ret i8 [[A]]1888;1889 %a = add nsw i8 %x, 31890 %m = call i8 @llvm.smax.i8(i8 %a, i8 -125)1891 ret i8 %m1892}1893 1894; This is handled by InstSimplify; testing here to confirm assert.1895 1896define i8 @smax_offset_overflow(i8 %x) {1897; CHECK-LABEL: @smax_offset_overflow(1898; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 31899; CHECK-NEXT: ret i8 [[A]]1900;1901 %a = add nsw i8 %x, 31902 %m = call i8 @llvm.smax.i8(i8 %a, i8 -126)1903 ret i8 %m1904}1905 1906; negative test - require nsw1907 1908define i8 @smax_offset_may_wrap(i8 %x) {1909; CHECK-LABEL: @smax_offset_may_wrap(1910; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 31911; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124)1912; CHECK-NEXT: ret i8 [[M]]1913;1914 %a = add i8 %x, 31915 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)1916 ret i8 %m1917}1918 1919; negative test1920 1921define i8 @smax_offset_uses(i8 %x) {1922; CHECK-LABEL: @smax_offset_uses(1923; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 31924; 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]]1927;1928 %a = add nsw i8 %x, 31929 call void @use(i8 %a)1930 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124)1931 ret i8 %m1932}1933 1934define <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]]1939;1940 %a = add nsw nuw <3 x i8> %x, <i8 124, i8 124, i8 124>1941 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %a, <3 x i8> <i8 -3, i8 -3, i8 -3>)1942 ret <3 x i8> %m1943}1944 1945; This is handled by InstSimplify; testing here to confirm assert.1946 1947define i8 @smin_offset_limit(i8 %x) {1948; CHECK-LABEL: @smin_offset_limit(1949; CHECK-NEXT: ret i8 -31950;1951 %a = add nsw i8 %x, 1251952 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)1953 ret i8 %m1954}1955 1956; This is handled by InstSimplify; testing here to confirm assert.1957 1958define i8 @smin_offset_overflow(i8 %x) {1959; CHECK-LABEL: @smin_offset_overflow(1960; CHECK-NEXT: ret i8 -31961;1962 %a = add nsw i8 %x, 1261963 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)1964 ret i8 %m1965}1966 1967; negative test - require nsw1968 1969define i8 @smin_offset_may_wrap(i8 %x) {1970; CHECK-LABEL: @smin_offset_may_wrap(1971; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 1241972; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3)1973; CHECK-NEXT: ret i8 [[M]]1974;1975 %a = add nuw i8 %x, 1241976 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)1977 ret i8 %m1978}1979 1980; negative test1981 1982define i8 @smin_offset_uses(i8 %x) {1983; CHECK-LABEL: @smin_offset_uses(1984; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 1241985; 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]]1988;1989 %a = add nsw i8 %x, 1241990 call void @use(i8 %a)1991 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3)1992 ret i8 %m1993}1994 1995; Note: 'nsw' must not propagate here.1996 1997define <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]]2002;2003 %a = add nsw nuw <3 x i8> %x, <i8 127, i8 127, i8 127>2004 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 130, i8 130, i8 130>)2005 ret <3 x i8> %m2006}2007 2008; This is handled by InstSimplify; testing here to confirm assert.2009 2010define i8 @umax_offset_limit(i8 %x) {2011; CHECK-LABEL: @umax_offset_limit(2012; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 32013; CHECK-NEXT: ret i8 [[A]]2014;2015 %a = add nuw i8 %x, 32016 %m = call i8 @llvm.umax.i8(i8 %a, i8 3)2017 ret i8 %m2018}2019 2020; This is handled by InstSimplify; testing here to confirm assert.2021 2022define i8 @umax_offset_overflow(i8 %x) {2023; CHECK-LABEL: @umax_offset_overflow(2024; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 32025; CHECK-NEXT: ret i8 [[A]]2026;2027 %a = add nuw i8 %x, 32028 %m = call i8 @llvm.umax.i8(i8 %a, i8 2)2029 ret i8 %m2030}2031 2032; negative test - require nuw2033 2034define i8 @umax_offset_may_wrap(i8 %x) {2035; CHECK-LABEL: @umax_offset_may_wrap(2036; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 32037; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4)2038; CHECK-NEXT: ret i8 [[M]]2039;2040 %a = add i8 %x, 32041 %m = call i8 @llvm.umax.i8(i8 %a, i8 4)2042 ret i8 %m2043}2044 2045; negative test2046 2047define i8 @umax_offset_uses(i8 %x) {2048; CHECK-LABEL: @umax_offset_uses(2049; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 32050; 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]]2053;2054 %a = add nuw i8 %x, 32055 call void @use(i8 %a)2056 %m = call i8 @llvm.umax.i8(i8 %a, i8 4)2057 ret i8 %m2058}2059 2060define i8 @umin_offset(i8 %x) {2061; CHECK-LABEL: @umin_offset(2062; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[X:%.*]], 02063; CHECK-NEXT: [[M:%.*]] = select i1 [[DOTNOT]], i8 -5, i8 -42064; CHECK-NEXT: ret i8 [[M]]2065;2066 %a = add nuw i8 %x, 2512067 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)2068 ret i8 %m2069}2070 2071; This is handled by InstSimplify; testing here to confirm assert.2072 2073define i8 @umin_offset_limit(i8 %x) {2074; CHECK-LABEL: @umin_offset_limit(2075; CHECK-NEXT: ret i8 -42076;2077 %a = add nuw i8 %x, 2522078 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)2079 ret i8 %m2080}2081 2082; This is handled by InstSimplify; testing here to confirm assert.2083 2084define i8 @umin_offset_overflow(i8 %x) {2085; CHECK-LABEL: @umin_offset_overflow(2086; CHECK-NEXT: ret i8 -42087;2088 %a = add nuw i8 %x, 2532089 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)2090 ret i8 %m2091}2092 2093; negative test - require nuw2094 2095define i8 @umin_offset_may_wrap(i8 %x) {2096; CHECK-LABEL: @umin_offset_may_wrap(2097; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], -52098; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4)2099; CHECK-NEXT: ret i8 [[M]]2100;2101 %a = add nsw i8 %x, 2512102 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)2103 ret i8 %m2104}2105 2106; negative test2107 2108define i8 @umin_offset_uses(i8 %x) {2109; CHECK-LABEL: @umin_offset_uses(2110; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], -52111; 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]]2114;2115 %a = add nuw i8 %x, 2512116 call void @use(i8 %a)2117 %m = call i8 @llvm.umin.i8(i8 %a, i8 252)2118 ret i8 %m2119}2120 2121; TODO: This could transform2122 2123define <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]]2128;2129 %a = add nuw <3 x i8> %x, <i8 poison, i8 64, i8 64>2130 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 13, i8 130, i8 130>)2131 ret <3 x i8> %r2132}2133 2134; Issue #52884 - this would assert because of a failure to simplify.2135 2136define i8 @smax_offset_simplify(i8 %x) {2137; CHECK-LABEL: @smax_offset_simplify(2138; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[X:%.*]], 502139; CHECK-NEXT: ret i8 [[TMP1]]2140;2141 %1 = add nuw nsw i8 50, %x2142 %m = call i8 @llvm.smax.i8(i8 %1, i8 -124)2143 ret i8 %m2144}2145 2146define <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]]2150;2151 %m1 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)2152 %m2 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)2153 ret <3 x i8> %m22154}2155 2156define 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]]2160;2161 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)2162 %m2 = call i8 @llvm.smin.i8(i8 -3, i8 %m1)2163 ret i8 %m22164}2165 2166define <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]]2170;2171 %m1 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>)2172 %m2 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 143, i8 poison>)2173 ret <3 x i8> %m22174}2175 2176; extra use is ok2177 2178define 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]]2184;2185 %m1 = call i8 @llvm.umin.i8(i8 140, i8 %x)2186 call void @use(i8 %m1)2187 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)2188 ret i8 %m22189}2190 2191; negative test - must have matching intrinsics2192 2193define i8 @smin_smax_reassoc_constants(i8 %x) {2194; CHECK-LABEL: @smin_smax_reassoc_constants(2195; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1:%.*]], i8 -3)2196; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M2]], i8 97)2197; CHECK-NEXT: ret i8 [[M3]]2198;2199 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97)2200 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 -3)2201 ret i8 %m22202}2203 2204define 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]]2209;2210 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)2211 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 42)2212 ret i8 %m22213}2214 2215define <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]]2220;2221 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %y)2222 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)2223 ret <3 x i8> %m22224}2225 2226define 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]]2231;2232 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)2233 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 42)2234 ret i8 %m22235}2236 2237define <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]]2242;2243 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> %y)2244 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>)2245 ret <3 x i8> %m22246}2247 2248define 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]]2254;2255 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)2256 call void @use(i8 %m1)2257 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42)2258 ret i8 %m22259}2260 2261define 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]]2266;2267 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)2268 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)2269 ret i8 %m22270}2271 2272define <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]]2277;2278 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)2279 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %y)2280 ret <3 x i8> %m22281}2282 2283define 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]]2288;2289 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)2290 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 %y)2291 ret i8 %m22292}2293 2294define <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]]2299;2300 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>)2301 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> %y)2302 ret <3 x i8> %m22303}2304 2305define 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]]2311;2312 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 42)2313 call void @use(i8 %m1)2314 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %y)2315 ret i8 %m22316}2317 2318define 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]]2323;2324 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)2325 %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %m1)2326 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)2327 ret i8 %m32328}2329 2330define 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]]2335;2336 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42)2337 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y)2338 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126)2339 ret i8 %m32340}2341 2342define 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]]2347;2348 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 42)2349 %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %m1)2350 %m3 = call i8 @llvm.smin.i8(i8 %m2, i8 126)2351 ret i8 %m32352}2353 2354define 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]]2359;2360 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42)2361 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8))2362 ret i8 %m22363}2364 2365define <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]]2370;2371 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2372 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2373 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)2374 ret <3 x i8> %r2375}2376 2377define <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]]2384;2385 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>2386 call void @use_vec(<3 x i8> %sx)2387 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2>2388 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)2389 ret <3 x i8> %r2390}2391 2392define <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]]2399;2400 %sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>2401 %sy = shufflevector <2 x i8> %y, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0>2402 call void @use_vec(<3 x i8> %sy)2403 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sx, <3 x i8> %sy)2404 ret <3 x i8> %r2405}2406 2407define <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]]2412;2413 %sx = shufflevector <4 x i8> %x, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>2414 %sy = shufflevector <4 x i8> %y, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3>2415 %r = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy)2416 ret <3 x i8> %r2417}2418 2419define <3 x i8> @smax_unary_shuffle_ops_lhs_const(<3 x i8> %x) {2420; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const(2421; CHECK-NEXT: [[X:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X1:%.*]], <3 x i8> <i8 1, i8 0, i8 2>)2422; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2423; CHECK-NEXT: ret <3 x i8> [[SX]]2424;2425 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2426 %r = call <3 x i8> @llvm.smax(<3 x i8> %sx, <3 x i8> <i8 0, i8 1, i8 2>)2427 ret <3 x i8> %r2428}2429 2430define <vscale x 3 x i8> @smax_unary_shuffle_ops_lhs_const_scalable(<vscale x 3 x i8> %x) {2431; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const_scalable(2432; CHECK-NEXT: [[R:%.*]] = call <vscale x 3 x i8> @llvm.smax.nxv3i8(<vscale x 3 x i8> [[SX:%.*]], <vscale x 3 x i8> splat (i8 42))2433; CHECK-NEXT: [[R1:%.*]] = shufflevector <vscale x 3 x i8> [[R]], <vscale x 3 x i8> poison, <vscale x 3 x i32> zeroinitializer2434; CHECK-NEXT: ret <vscale x 3 x i8> [[R1]]2435;2436 %sx = shufflevector <vscale x 3 x i8> %x, <vscale x 3 x i8> poison, <vscale x 3 x i32> zeroinitializer2437 %r = call <vscale x 3 x i8> @llvm.smax(<vscale x 3 x i8> %sx, <vscale x 3 x i8> splat (i8 42))2438 ret <vscale x 3 x i8> %r2439}2440 2441define <3 x i8> @smax_unary_shuffle_ops_lhs_const_widening(<2 x i8> %x) {2442; CHECK-LABEL: @smax_unary_shuffle_ops_lhs_const_widening(2443; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X1:%.*]], <2 x i8> <i8 1, i8 0>)2444; CHECK-NEXT: [[SX:%.*]] = shufflevector <2 x i8> [[X]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 poison>2445; CHECK-NEXT: ret <3 x i8> [[SX]]2446;2447 %sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 poison>2448 %r = call <3 x i8> @llvm.smax(<3 x i8> %sx, <3 x i8> <i8 0, i8 1, i8 2>)2449 ret <3 x i8> %r2450}2451 2452; negative test - must have 2 shuffles2453 2454define <3 x i8> @smax_unary_shuffle_ops_unshuffled_op(<3 x i8> %x, <3 x i8> %y) {2455; CHECK-LABEL: @smax_unary_shuffle_ops_unshuffled_op(2456; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>2457; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[Y:%.*]])2458; CHECK-NEXT: ret <3 x i8> [[R]]2459;2460 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>2461 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %y)2462 ret <3 x i8> %r2463}2464 2465; negative test - must have identical masks2466 2467define <3 x i8> @smax_unary_shuffle_ops_wrong_mask(<3 x i8> %x, <3 x i8> %y) {2468; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_mask(2469; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>2470; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2471; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])2472; CHECK-NEXT: ret <3 x i8> [[R]]2473;2474 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2>2475 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2476 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)2477 ret <3 x i8> %r2478}2479 2480; negative test - must be unary shuffles2481 2482define <3 x i8> @smax_unary_shuffle_ops_wrong_shuf(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) {2483; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_shuf(2484; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]], <3 x i32> <i32 1, i32 0, i32 3>2485; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> [[Z]], <3 x i32> <i32 1, i32 0, i32 3>2486; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])2487; CHECK-NEXT: ret <3 x i8> [[R]]2488;2489 %sx = shufflevector <3 x i8> %x, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>2490 %sy = shufflevector <3 x i8> %y, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3>2491 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy)2492 ret <3 x i8> %r2493}2494 2495; negative test - too many uses2496 2497define <3 x i8> @smin_unary_shuffle_ops_uses(<3 x i8> %x, <3 x i8> %y) {2498; CHECK-LABEL: @smin_unary_shuffle_ops_uses(2499; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2500; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]])2501; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2502; CHECK-NEXT: call void @use_vec(<3 x i8> [[SY]])2503; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]])2504; CHECK-NEXT: ret <3 x i8> [[R]]2505;2506 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2507 call void @use_vec(<3 x i8> %sx)2508 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2509 call void @use_vec(<3 x i8> %sy)2510 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy)2511 ret <3 x i8> %r2512}2513 2514; negative test - too many uses2515 2516define <3 x i8> @smin_unary_shuffle_ops_uses_const(<3 x i8> %x, <3 x i8> %y) {2517; CHECK-LABEL: @smin_unary_shuffle_ops_uses_const(2518; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2519; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]])2520; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[SX]], <3 x i8> <i8 1, i8 2, i8 3>)2521; CHECK-NEXT: ret <3 x i8> [[R]]2522;2523 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2>2524 call void @use_vec(<3 x i8> %sx)2525 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> <i8 1, i8 2, i8 3>)2526 ret <3 x i8> %r2527}2528 2529; This would assert/crash because we tried to zext to i1.2530 2531@g = external dso_local global i32, align 42532 2533define i1 @PR57986() {2534; CHECK-LABEL: @PR57986(2535; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1)2536;2537 %umin = call i1 @llvm.umin.i1(i1 ptrtoint (ptr @g to i1), i1 true)2538 ret i1 %umin2539}2540 2541define i8 @fold_umax_with_knownbits_info(i8 %a, i8 %b) {2542; CHECK-LABEL: @fold_umax_with_knownbits_info(2543; CHECK-NEXT: entry:2544; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 12545; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 12546; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]2547; CHECK-NEXT: ret i8 [[SUB]]2548;2549entry:2550 %a1 = or i8 %a, 12551 %a2 = shl i8 %b, 12552 %sub = sub i8 %a1, %a22553 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)2554 ret i8 %val2555}2556 2557define <3 x i8> @fold_umax_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {2558; CHECK-LABEL: @fold_umax_with_knownbits_info_poison_in_splat(2559; CHECK-NEXT: entry:2560; CHECK-NEXT: [[A1:%.*]] = or <3 x i8> [[A:%.*]], splat (i8 1)2561; CHECK-NEXT: [[A2:%.*]] = shl <3 x i8> [[B:%.*]], splat (i8 1)2562; CHECK-NEXT: [[SUB:%.*]] = sub <3 x i8> [[A1]], [[A2]]2563; CHECK-NEXT: ret <3 x i8> [[SUB]]2564;2565entry:2566 %a1 = or <3 x i8> %a, <i8 1, i8 1, i8 1>2567 %a2 = shl <3 x i8> %b, <i8 1, i8 1, i8 1>2568 %sub = sub <3 x i8> %a1, %a22569 %val = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sub, <3 x i8> <i8 1, i8 poison, i8 1>)2570 ret <3 x i8> %val2571}2572 2573define i8 @fold_umin_with_knownbits_info(i8 %a, i8 %b) {2574; CHECK-LABEL: @fold_umin_with_knownbits_info(2575; CHECK-NEXT: entry:2576; CHECK-NEXT: ret i8 32577;2578entry:2579 %a1 = or i8 %a, 32580 %a2 = shl i8 %b, 22581 %sub = sub i8 %a1, %a22582 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)2583 ret i8 %val2584}2585 2586define <3 x i8> @fold_umin_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) {2587; CHECK-LABEL: @fold_umin_with_knownbits_info_poison_in_splat(2588; CHECK-NEXT: entry:2589; CHECK-NEXT: ret <3 x i8> splat (i8 3)2590;2591entry:2592 %a1 = or <3 x i8> %a, <i8 3, i8 3, i8 3>2593 %a2 = shl <3 x i8> %b, <i8 2, i8 2, i8 2>2594 %sub = sub <3 x i8> %a1, %a22595 %val = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sub, <3 x i8> <i8 3, i8 poison, i8 3>)2596 ret <3 x i8> %val2597}2598 2599define i8 @fold_umax_with_knownbits_info_fail(i8 %a, i8 %b) {2600; CHECK-LABEL: @fold_umax_with_knownbits_info_fail(2601; CHECK-NEXT: entry:2602; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 22603; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 12604; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]2605; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umax.i8(i8 [[SUB]], i8 1)2606; CHECK-NEXT: ret i8 [[VAL]]2607;2608entry:2609 %a1 = or i8 %a, 22610 %a2 = shl i8 %b, 12611 %sub = sub i8 %a1, %a22612 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1)2613 ret i8 %val2614}2615 2616define i8 @fold_umin_with_knownbits_info_fail(i8 %a, i8 %b) {2617; CHECK-LABEL: @fold_umin_with_knownbits_info_fail(2618; CHECK-NEXT: entry:2619; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 12620; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 22621; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]]2622; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umin.i8(i8 [[SUB]], i8 3)2623; CHECK-NEXT: ret i8 [[VAL]]2624;2625entry:2626 %a1 = or i8 %a, 12627 %a2 = shl i8 %b, 22628 %sub = sub i8 %a1, %a22629 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3)2630 ret i8 %val2631}2632 2633define i8 @test_umax_and(i8 %x, i8 %y) {2634; CHECK-LABEL: @test_umax_and(2635; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])2636; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -642637; CHECK-NEXT: ret i8 [[RES1]]2638;2639 %x1 = and i8 %x, -642640 %y1 = and i8 %y, -642641 %res = call i8 @llvm.umax.i8(i8 %x1, i8 %y1)2642 ret i8 %res2643}2644 2645define i8 @test_umin_and(i8 %x, i8 %y) {2646; CHECK-LABEL: @test_umin_and(2647; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])2648; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -642649; CHECK-NEXT: ret i8 [[RES1]]2650;2651 %x1 = and i8 %x, -642652 %y1 = and i8 %y, -642653 %res = call i8 @llvm.umin.i8(i8 %x1, i8 %y1)2654 ret i8 %res2655}2656 2657define i8 @test_smax_and(i8 %x, i8 %y) {2658; CHECK-LABEL: @test_smax_and(2659; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])2660; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -642661; CHECK-NEXT: ret i8 [[RES1]]2662;2663 %x1 = and i8 %x, -642664 %y1 = and i8 %y, -642665 %res = call i8 @llvm.smax.i8(i8 %x1, i8 %y1)2666 ret i8 %res2667}2668 2669define i8 @test_smin_and(i8 %x, i8 %y) {2670; CHECK-LABEL: @test_smin_and(2671; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]])2672; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -642673; CHECK-NEXT: ret i8 [[RES1]]2674;2675 %x1 = and i8 %x, -642676 %y1 = and i8 %y, -642677 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)2678 ret i8 %res2679}2680 2681define i8 @test_smin_and_mismatch(i8 %x, i8 %y) {2682; CHECK-LABEL: @test_smin_and_mismatch(2683; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], -642684; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], -322685; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])2686; CHECK-NEXT: ret i8 [[RES]]2687;2688 %x1 = and i8 %x, -642689 %y1 = and i8 %y, -322690 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)2691 ret i8 %res2692}2693 2694define i8 @test_smin_and_non_negated_pow2(i8 %x, i8 %y) {2695; CHECK-LABEL: @test_smin_and_non_negated_pow2(2696; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 312697; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 312698; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])2699; CHECK-NEXT: ret i8 [[RES]]2700;2701 %x1 = and i8 %x, 312702 %y1 = and i8 %y, 312703 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)2704 ret i8 %res2705}2706 2707define i8 @test_smin_and_multiuse(i8 %x, i8 %y) {2708; CHECK-LABEL: @test_smin_and_multiuse(2709; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 312710; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 312711; CHECK-NEXT: call void @use(i8 [[Y1]])2712; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]])2713; CHECK-NEXT: ret i8 [[RES]]2714;2715 %x1 = and i8 %x, 312716 %y1 = and i8 %y, 312717 call void @use(i8 %y1)2718 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1)2719 ret i8 %res2720}2721