brintos

brintos / llvm-project-archived public Read only

0
0
Text · 89.4 KiB · 52bc363 Raw
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