brintos

brintos / llvm-project-archived public Read only

0
0
Text · 37.7 KiB · c5af574 Raw
1147 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare i5 @llvm.umin.i5(i5, i5)5declare <2 x i8> @llvm.smin.v2i8(<2 x i8>, <2 x i8>)6declare <2 x i8> @llvm.smax.v2i8(<2 x i8>, <2 x i8>)7declare <2 x i8> @llvm.umin.v2i8(<2 x i8>, <2 x i8>)8declare <2 x i8> @llvm.umax.v2i8(<2 x i8>, <2 x i8>)9 10declare i8 @llvm.smax.i8(i8, i8)11declare i8 @llvm.smin.i8(i8, i8)12declare i8 @llvm.umax.i8(i8, i8)13declare i8 @llvm.umin.i8(i8, i8)14 15define i32 @max_na_b_minux_na(i32 %A, i32 %B) {16; CHECK-LABEL: define {{[^@]+}}@max_na_b_minux_na17; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {18; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -119; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])20; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]21; CHECK-NEXT:    ret i32 [[X]]22;23  %not = xor i32 %A, -124  %l0 = icmp ult i32 %not, %B25  %l1 = select i1 %l0, i32 %not, i32 %B26  %x = sub i32 %l1, %not27  ret i32 %x28}29 30define i32 @na_minus_max_na_b(i32 %A, i32 %B) {31; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_b32; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {33; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -134; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])35; CHECK-NEXT:    ret i32 [[X]]36;37  %not = xor i32 %A, -138  %l0 = icmp ult i32 %not, %B39  %l1 = select i1 %l0, i32 %not, i32 %B40  %x = sub i32 %not, %l141  ret i32 %x42}43 44define i5 @sub_umin(i5 %a, i5 %b) {45; CHECK-LABEL: define {{[^@]+}}@sub_umin46; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]]) {47; CHECK-NEXT:    [[R:%.*]] = call i5 @llvm.usub.sat.i5(i5 [[A]], i5 [[B]])48; CHECK-NEXT:    ret i5 [[R]]49;50  %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)51  %r = sub i5 %a, %umin52  ret i5 %r53}54 55define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) {56; CHECK-LABEL: define {{[^@]+}}@sub_umin_commute_vec57; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {58; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> [[A]])59; CHECK-NEXT:    ret <2 x i8> [[R]]60;61  %umin = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %b, <2 x i8> %a)62  %r = sub <2 x i8> %b, %umin63  ret <2 x i8> %r64}65 66define i5 @sub_umin_uses(i5 %a, i5 %b, ptr %p) {67; CHECK-LABEL: define {{[^@]+}}@sub_umin_uses68; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]], ptr [[P:%.*]]) {69; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A]], i5 [[B]])70; CHECK-NEXT:    store i5 [[UMIN]], ptr [[P]], align 171; CHECK-NEXT:    [[R:%.*]] = sub i5 [[A]], [[UMIN]]72; CHECK-NEXT:    ret i5 [[R]]73;74  %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)75  store i5 %umin, ptr %p76  %r = sub i5 %a, %umin77  ret i5 %r78}79 80define i5 @sub_umin_no_common_op(i5 %a, i5 %b, i5 %c) {81; CHECK-LABEL: define {{[^@]+}}@sub_umin_no_common_op82; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]], i5 [[C:%.*]]) {83; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A]], i5 [[B]])84; CHECK-NEXT:    [[R:%.*]] = sub i5 [[C]], [[UMIN]]85; CHECK-NEXT:    ret i5 [[R]]86;87  %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)88  %r = sub i5 %c, %umin89  ret i5 %r90}91 92define i32 @max_b_na_minus_na(i32 %A, i32 %B) {93; CHECK-LABEL: define {{[^@]+}}@max_b_na_minus_na94; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {95; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -196; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])97; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]98; CHECK-NEXT:    ret i32 [[X]]99;100  %not = xor i32 %A, -1101  %l0 = icmp ugt i32 %not, %B102  %l1 = select i1 %l0, i32 %B, i32 %not103  %x = sub i32 %l1, %not104  ret i32 %x105}106 107define i32 @na_minus_max_b_na(i32 %A, i32 %B) {108; CHECK-LABEL: define {{[^@]+}}@na_minus_max_b_na109; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {110; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1111; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])112; CHECK-NEXT:    ret i32 [[X]]113;114  %not = xor i32 %A, -1115  %l0 = icmp ugt i32 %not, %B116  %l1 = select i1 %l0, i32 %B, i32 %not117  %x = sub i32 %not, %l1118  ret i32 %x119}120 121 122define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) {123; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na124; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {125; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])126; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]127; CHECK-NEXT:    ret i32 [[X]]128;129  %B =  xor i32 %Bi, -1130  %not = xor i32 %A, -1131  %l0 = icmp ult i32 %not, %B132  %l1 = select i1 %l0, i32 %not, i32 %B133  %x = sub i32 %l1, %not134  ret i32 %x135}136 137define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) {138; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi139; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {140; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])141; CHECK-NEXT:    ret i32 [[X]]142;143  %B =  xor i32 %Bi, -1144  %not = xor i32 %A, -1145  %l0 = icmp ult i32 %not, %B146  %l1 = select i1 %l0, i32 %not, i32 %B147  %x = sub i32 %not, %l1148  ret i32 %x149}150 151define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) {152; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na153; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {154; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])155; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]156; CHECK-NEXT:    ret i32 [[X]]157;158  %B =  xor i32 %Bi, -1159  %not = xor i32 %A, -1160  %l0 = icmp ugt i32 %not, %B161  %l1 = select i1 %l0, i32 %B, i32 %not162  %x = sub i32 %l1, %not163  ret i32 %x164}165 166define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) {167; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na168; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {169; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])170; CHECK-NEXT:    ret i32 [[X]]171;172  %B =  xor i32 %Bi, -1173  %not = xor i32 %A, -1174  %l0 = icmp ugt i32 %not, %B175  %l1 = select i1 %l0, i32 %B, i32 %not176  %x = sub i32 %not, %l1177  ret i32 %x178}179 180 181define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) {182; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use183; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {184; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 -32)185; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1186; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]187; CHECK-NEXT:    call void @use32(i32 [[L1]])188; CHECK-NEXT:    ret i32 [[X]]189;190  %not = xor i32 %A, -1191  %l0 = icmp ult i32 %not, 31192  %l1 = select i1 %l0, i32 %not, i32 31193  %x = sub i32 %l1, %not194  call void @use32(i32 %l1)195  ret i32 %x196}197 198define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) {199; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use200; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {201; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 -32)202; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1203; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]204; CHECK-NEXT:    call void @use32(i32 [[L1]])205; CHECK-NEXT:    ret i32 [[X]]206;207  %not = xor i32 %A, -1208  %l0 = icmp ult i32 %not, 31209  %l1 = select i1 %l0, i32 %not, i32 31210  %x = sub i32 %not, %l1211  call void @use32(i32 %l1)212  ret i32 %x213}214 215define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) {216; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use217; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {218; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])219; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1220; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]221; CHECK-NEXT:    call void @use32(i32 [[L1]])222; CHECK-NEXT:    ret i32 [[X]]223;224  %not = xor i32 %A, -1225  %B = xor i32 %Bi, -1226  %l0 = icmp ult i32 %B, %not227  %l1 = select i1 %l0, i32 %B, i32 %not228  %x = sub i32 %l1, %not229  call void @use32(i32 %l1)230  ret i32 %x231}232 233define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) {234; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use235; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {236; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])237; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1238; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]239; CHECK-NEXT:    call void @use32(i32 [[L1]])240; CHECK-NEXT:    ret i32 [[X]]241;242  %not = xor i32 %A, -1243  %B = xor i32 %Bi, -1244  %l0 = icmp ult i32 %B, %not245  %l1 = select i1 %l0, i32 %B, i32 %not246  %x = sub i32 %not, %l1247  call void @use32(i32 %l1)248  ret i32 %x249}250 251 252define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) {253; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use2254; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {255; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1256; CHECK-NEXT:    [[L1:%.*]] = call i32 @llvm.umin.i32(i32 [[NOT]], i32 31)257; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]258; CHECK-NEXT:    call void @use32(i32 [[L1]])259; CHECK-NEXT:    call void @use32(i32 [[NOT]])260; CHECK-NEXT:    ret i32 [[X]]261;262  %not = xor i32 %A, -1263  %l0 = icmp ult i32 %not, 31264  %l1 = select i1 %l0, i32 %not, i32 31265  %x = sub i32 %l1, %not266  call void @use32(i32 %l1)267  call void @use32(i32 %not)268  ret i32 %x269}270 271define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) {272; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use2273; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {274; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1275; CHECK-NEXT:    [[L1:%.*]] = call i32 @llvm.umin.i32(i32 [[NOT]], i32 31)276; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]277; CHECK-NEXT:    call void @use32(i32 [[L1]])278; CHECK-NEXT:    call void @use32(i32 [[NOT]])279; CHECK-NEXT:    ret i32 [[X]]280;281  %not = xor i32 %A, -1282  %l0 = icmp ult i32 %not, 31283  %l1 = select i1 %l0, i32 %not, i32 31284  %x = sub i32 %not, %l1285  call void @use32(i32 %l1)286  call void @use32(i32 %not)287  ret i32 %x288}289 290define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) {291; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use2292; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {293; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1294; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])295; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1296; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]297; CHECK-NEXT:    call void @use32(i32 [[L1]])298; CHECK-NEXT:    call void @use32(i32 [[NOT]])299; CHECK-NEXT:    ret i32 [[X]]300;301  %not = xor i32 %A, -1302  %B = xor i32 %Bi, -1303  %l0 = icmp ult i32 %B, %not304  %l1 = select i1 %l0, i32 %B, i32 %not305  %x = sub i32 %l1, %not306  call void @use32(i32 %l1)307  call void @use32(i32 %not)308  ret i32 %x309}310 311define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) {312; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use2313; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {314; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1315; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])316; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1317; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]318; CHECK-NEXT:    call void @use32(i32 [[L1]])319; CHECK-NEXT:    call void @use32(i32 [[NOT]])320; CHECK-NEXT:    ret i32 [[X]]321;322  %not = xor i32 %A, -1323  %B = xor i32 %Bi, -1324  %l0 = icmp ult i32 %B, %not325  %l1 = select i1 %l0, i32 %B, i32 %not326  %x = sub i32 %not, %l1327  call void @use32(i32 %l1)328  call void @use32(i32 %not)329  ret i32 %x330}331 332define i8 @umin_not_sub(i8 %x, i8 %y) {333; CHECK-LABEL: define {{[^@]+}}@umin_not_sub334; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {335; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])336; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP1]], -1337; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]338; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[TMP1]], [[Y]]339; CHECK-NEXT:    call void @use8(i8 [[SUBX]])340; CHECK-NEXT:    call void @use8(i8 [[SUBY]])341; CHECK-NEXT:    ret i8 [[MINXY]]342;343  %nx = xor i8 %x, -1344  %ny = xor i8 %y, -1345  %cmpxy = icmp ult i8 %nx, %ny346  %minxy = select i1 %cmpxy, i8 %nx, i8 %ny347  %subx = sub i8 %nx, %minxy348  %suby = sub i8 %ny, %minxy349  call void @use8(i8 %subx)350  call void @use8(i8 %suby)351  ret i8 %minxy352}353 354define i8 @umin_not_sub_rev(i8 %x, i8 %y) {355; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_rev356; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {357; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])358; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP1]], -1359; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]360; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[Y]], [[TMP1]]361; CHECK-NEXT:    call void @use8(i8 [[SUBX]])362; CHECK-NEXT:    call void @use8(i8 [[SUBY]])363; CHECK-NEXT:    ret i8 [[MINXY]]364;365  %nx = xor i8 %x, -1366  %ny = xor i8 %y, -1367  %cmpxy = icmp ult i8 %nx, %ny368  %minxy = select i1 %cmpxy, i8 %nx, i8 %ny369  %subx = sub i8 %minxy, %nx370  %suby = sub i8 %minxy, %ny371  call void @use8(i8 %subx)372  call void @use8(i8 %suby)373  ret i8 %minxy374}375 376define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) {377; CHECK-LABEL: define {{[^@]+}}@umin3_not_all_ops_extra_uses_invert_subs378; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {379; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Z]])380; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[TMP1]])381; CHECK-NEXT:    [[MINXYZ:%.*]] = xor i8 [[TMP2]], -1382; CHECK-NEXT:    [[XMIN:%.*]] = sub i8 [[TMP2]], [[X]]383; CHECK-NEXT:    [[YMIN:%.*]] = sub i8 [[TMP2]], [[Y]]384; CHECK-NEXT:    [[ZMIN:%.*]] = sub i8 [[TMP2]], [[Z]]385; CHECK-NEXT:    call void @use8(i8 [[MINXYZ]])386; CHECK-NEXT:    call void @use8(i8 [[XMIN]])387; CHECK-NEXT:    call void @use8(i8 [[YMIN]])388; CHECK-NEXT:    call void @use8(i8 [[ZMIN]])389; CHECK-NEXT:    ret void390;391  %xn = xor i8 %x, -1392  %yn = xor i8 %y, -1393  %zn = xor i8 %z, -1394  %cmpxz = icmp ult i8 %xn, %zn395  %minxz = select i1 %cmpxz, i8 %xn, i8 %zn396  %cmpxyz = icmp ult i8 %minxz, %yn397  %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn398  %xmin = sub i8 %xn, %minxyz399  %ymin = sub i8 %yn, %minxyz400  %zmin = sub i8 %zn, %minxyz401  call void @use8(i8 %minxyz)402  call void @use8(i8 %xmin)403  call void @use8(i8 %ymin)404  call void @use8(i8 %zmin)405  ret void406}407 408; Handle this pattern with extra uses because it shows up in benchmarks.409; ~X - Min/Max(~X, Y) -> ~Min/Max(X, ~Y) - X410; ~X - Min/Max(Y, ~X) -> ~Min/Max(X, ~Y) - X411; Min/Max(~X, Y) - ~X -> X - ~Min/Max(X, ~Y)412; Min/Max(Y, ~X) - ~X -> X - ~Min/Max(X, ~Y)413 414define i8 @umin_not_sub_intrinsic_commute0(i8 %x, i8 %y) {415; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_intrinsic_commute0416; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {417; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1418; CHECK-NEXT:    call void @use8(i8 [[NY]])419; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])420; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1421; CHECK-NEXT:    call void @use8(i8 [[M]])422; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]423; CHECK-NEXT:    ret i8 [[SUBX]]424;425  %nx = xor i8 %x, -1426  %ny = xor i8 %y, -1427  call void @use8(i8 %ny)428  %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)429  call void @use8(i8 %m)430  %subx = sub i8 %nx, %m431  ret i8 %subx432}433 434define i8 @umax_not_sub_intrinsic_commute1(i8 %x, i8 %y) {435; CHECK-LABEL: define {{[^@]+}}@umax_not_sub_intrinsic_commute1436; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {437; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1438; CHECK-NEXT:    call void @use8(i8 [[NY]])439; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])440; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1441; CHECK-NEXT:    call void @use8(i8 [[M]])442; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]443; CHECK-NEXT:    ret i8 [[SUBX]]444;445  %nx = xor i8 %x, -1446  %ny = xor i8 %y, -1447  call void @use8(i8 %ny)448  %m = call i8 @llvm.umax.i8(i8 %ny, i8 %nx)449  call void @use8(i8 %m)450  %subx = sub i8 %nx, %m451  ret i8 %subx452}453 454define i8 @smin_not_sub_intrinsic_commute2(i8 %x, i8 %y) {455; CHECK-LABEL: define {{[^@]+}}@smin_not_sub_intrinsic_commute2456; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {457; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1458; CHECK-NEXT:    call void @use8(i8 [[NY]])459; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])460; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1461; CHECK-NEXT:    call void @use8(i8 [[M]])462; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]463; CHECK-NEXT:    ret i8 [[SUBX]]464;465  %nx = xor i8 %x, -1466  %ny = xor i8 %y, -1467  call void @use8(i8 %ny)468  %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)469  call void @use8(i8 %m)470  %subx = sub i8 %m, %nx471  ret i8 %subx472}473 474define i8 @smax_not_sub_intrinsic_commute3(i8 %x, i8 %y) {475; CHECK-LABEL: define {{[^@]+}}@smax_not_sub_intrinsic_commute3476; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {477; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1478; CHECK-NEXT:    call void @use8(i8 [[NY]])479; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])480; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1481; CHECK-NEXT:    call void @use8(i8 [[M]])482; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]483; CHECK-NEXT:    ret i8 [[SUBX]]484;485  %nx = xor i8 %x, -1486  %ny = xor i8 %y, -1487  call void @use8(i8 %ny)488  %m = call i8 @llvm.smax.i8(i8 %ny, i8 %nx)489  call void @use8(i8 %m)490  %subx = sub i8 %m, %nx491  ret i8 %subx492}493 494; negative test - don't increase instruction count495 496define i8 @umin_not_sub_intrinsic_uses(i8 %x, i8 %y) {497; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_intrinsic_uses498; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {499; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X]], -1500; CHECK-NEXT:    call void @use8(i8 [[NX]])501; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1502; CHECK-NEXT:    call void @use8(i8 [[NY]])503; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])504; CHECK-NEXT:    call void @use8(i8 [[M]])505; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[NX]], [[M]]506; CHECK-NEXT:    ret i8 [[SUBX]]507;508  %nx = xor i8 %x, -1509  call void @use8(i8 %nx)510  %ny = xor i8 %y, -1511  call void @use8(i8 %ny)512  %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)513  call void @use8(i8 %m)514  %subx = sub i8 %nx, %m515  ret i8 %subx516}517 518define i8 @umax_sub_op0(i8 %x, i8 %y) {519; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0520; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {521; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X]], i8 [[Y]])522; CHECK-NEXT:    ret i8 [[R]]523;524  %u = call i8 @llvm.umax.i8(i8 %y, i8 %x)525  %r = sub i8 %u, %y526  ret i8 %r527}528 529define <2 x i8> @umax_sub_op0_vec_commute(<2 x i8> %x, <2 x i8> %y) {530; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0_vec_commute531; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {532; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])533; CHECK-NEXT:    ret <2 x i8> [[R]]534;535  %u = call <2 x i8> @llvm.umax.v2i8(<2 x i8> %x, <2 x i8> %y)536  %r = sub <2 x i8> %u, %y537  ret <2 x i8> %r538}539 540define i8 @umax_sub_op0_use(i8 %x, i8 %y) {541; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0_use542; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {543; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])544; CHECK-NEXT:    call void @use8(i8 [[U]])545; CHECK-NEXT:    [[R:%.*]] = sub i8 [[U]], [[Y]]546; CHECK-NEXT:    ret i8 [[R]]547;548  %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)549  call void @use8(i8 %u)550  %r = sub i8 %u, %y551  ret i8 %r552}553 554define i8 @umax_sub_op1(i8 %x, i8 %y) {555; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1556; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {557; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X]], i8 [[Y]])558; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]559; CHECK-NEXT:    ret i8 [[R]]560;561  %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)562  %r = sub i8 %y, %u563  ret i8 %r564}565 566define <2 x i8> @umax_sub_op1_vec_commute(<2 x i8> %x, <2 x i8> %y) {567; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1_vec_commute568; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {569; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])570; CHECK-NEXT:    [[R:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]571; CHECK-NEXT:    ret <2 x i8> [[R]]572;573  %u = call <2 x i8> @llvm.umax.v2i8(<2 x i8> %y, <2 x i8> %x)574  %r = sub <2 x i8> %y, %u575  ret <2 x i8> %r576}577 578define i8 @umax_sub_op1_use(i8 %x, i8 %y) {579; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1_use580; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {581; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])582; CHECK-NEXT:    call void @use8(i8 [[U]])583; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[U]]584; CHECK-NEXT:    ret i8 [[R]]585;586  %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)587  call void @use8(i8 %u)588  %r = sub i8 %y, %u589  ret i8 %r590}591 592define i8 @umin_sub_op1(i8 %x, i8 %y) {593; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1594; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {595; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])596; CHECK-NEXT:    ret i8 [[R]]597;598  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)599  %r = sub i8 %y, %u600  ret i8 %r601}602 603define i8 @umin_sub_op1_commute(i8 %x, i8 %y) {604; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_commute605; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {606; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])607; CHECK-NEXT:    ret i8 [[R]]608;609  %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)610  %r = sub i8 %y, %u611  ret i8 %r612}613 614define i8 @umin_sub_op0(i8 %x, i8 %y) {615; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0616; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {617; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])618; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]619; CHECK-NEXT:    ret i8 [[R]]620;621  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)622  %r = sub i8 %u, %y623  ret i8 %r624}625 626define i8 @umin_sub_op0_commute(i8 %x, i8 %y) {627; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_commute628; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {629; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])630; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]631; CHECK-NEXT:    ret i8 [[R]]632;633  %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)634  %r = sub i8 %u, %y635  ret i8 %r636}637 638define i8 @umin_sub_op1_use(i8 %x, i8 %y) {639; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_use640; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {641; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])642; CHECK-NEXT:    call void @use8(i8 [[U]])643; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[U]]644; CHECK-NEXT:    ret i8 [[R]]645;646  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)647  call void @use8(i8 %u)648  %r = sub i8 %y, %u649  ret i8 %r650}651 652define i8 @umin_sub_op0_use(i8 %x, i8 %y) {653; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_use654; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {655; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])656; CHECK-NEXT:    call void @use8(i8 [[U]])657; CHECK-NEXT:    [[R:%.*]] = sub i8 [[U]], [[Y]]658; CHECK-NEXT:    ret i8 [[R]]659;660  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)661  call void @use8(i8 %u)662  %r = sub i8 %u, %y663  ret i8 %r664}665 666;667; sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y)668; sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y)669;670 671define i8 @diff_add_smin(i8 %x, i8 %y) {672; CHECK-LABEL: define {{[^@]+}}@diff_add_smin673; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {674; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])675; CHECK-NEXT:    ret i8 [[S]]676;677  %a = add i8 %x, %y678  %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)679  %s = sub i8 %a, %m680  ret i8 %s681}682 683define i8 @diff_add_smax(i8 %x, i8 %y) {684; CHECK-LABEL: define {{[^@]+}}@diff_add_smax685; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {686; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])687; CHECK-NEXT:    ret i8 [[S]]688;689  %a = add i8 %x, %y690  %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)691  %s = sub i8 %a, %m692  ret i8 %s693}694 695define i8 @diff_add_umin(i8 %x, i8 %y) {696; CHECK-LABEL: define {{[^@]+}}@diff_add_umin697; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {698; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])699; CHECK-NEXT:    ret i8 [[S]]700;701  %a = add i8 %x, %y702  %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)703  %s = sub i8 %a, %m704  ret i8 %s705}706 707define i8 @diff_add_umax(i8 %x, i8 %y) {708; CHECK-LABEL: define {{[^@]+}}@diff_add_umax709; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {710; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])711; CHECK-NEXT:    ret i8 [[S]]712;713  %a = add i8 %x, %y714  %m = call i8 @llvm.umax.i8(i8 %y, i8 %x)715  %s = sub i8 %a, %m716  ret i8 %s717}718 719define i8 @diff_add_smin_use(i8 %x, i8 %y) {720; CHECK-LABEL: define {{[^@]+}}@diff_add_smin_use721; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {722; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])723; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])724; CHECK-NEXT:    call void @use8(i8 [[M]])725; CHECK-NEXT:    ret i8 [[S]]726;727  %a = add i8 %x, %y728  %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)729  %s = sub i8 %a, %m730  call void @use8(i8 %m)731  ret i8 %s732}733 734define i8 @diff_add_use_smax(i8 %x, i8 %y) {735; CHECK-LABEL: define {{[^@]+}}@diff_add_use_smax736; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {737; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]738; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])739; CHECK-NEXT:    call void @use8(i8 [[A]])740; CHECK-NEXT:    ret i8 [[S]]741;742  %a = add i8 %x, %y743  %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)744  %s = sub i8 %a, %m745  call void @use8(i8 %a)746  ret i8 %s747}748 749define i8 @diff_add_use_umin_use(i8 %x, i8 %y) {750; CHECK-LABEL: define {{[^@]+}}@diff_add_use_umin_use751; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {752; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]753; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])754; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]755; CHECK-NEXT:    call void @use8(i8 [[A]])756; CHECK-NEXT:    call void @use8(i8 [[M]])757; CHECK-NEXT:    ret i8 [[S]]758;759  %a = add i8 %x, %y760  %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)761  %s = sub i8 %a, %m762  call void @use8(i8 %a)763  call void @use8(i8 %m)764  ret i8 %s765}766 767; sub(add(X,Y),umin(Y,Z)) --> add(X,usubsat(Y,Z))768 769define i8 @sub_add_umin(i8 %x, i8 %y, i8 %z) {770; CHECK-LABEL: define {{[^@]+}}@sub_add_umin771; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {772; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])773; CHECK-NEXT:    [[S:%.*]] = add i8 [[X]], [[TMP1]]774; CHECK-NEXT:    ret i8 [[S]]775;776  %a = add i8 %x, %y777  %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)778  %s = sub i8 %a, %m779  ret i8 %s780}781 782define i8 @sub_add_umin_commute_umin(i8 %x, i8 %y, i8 %z) {783; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_umin784; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {785; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])786; CHECK-NEXT:    [[S:%.*]] = add i8 [[X]], [[TMP1]]787; CHECK-NEXT:    ret i8 [[S]]788;789  %a = add i8 %x, %y790  %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)791  %s = sub i8 %a, %m792  ret i8 %s793}794 795define i8 @sub_add_umin_commute_add(i8 %x, i8 %y, i8 %z) {796; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add797; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {798; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])799; CHECK-NEXT:    [[S:%.*]] = add i8 [[X]], [[TMP1]]800; CHECK-NEXT:    ret i8 [[S]]801;802  %a = add i8 %y, %x803  %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)804  %s = sub i8 %a, %m805  ret i8 %s806}807 808define i8 @sub_add_umin_commute_add_umin(i8 %x, i8 %y, i8 %z) {809; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add_umin810; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {811; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])812; CHECK-NEXT:    [[S:%.*]] = add i8 [[X]], [[TMP1]]813; CHECK-NEXT:    ret i8 [[S]]814;815  %a = add i8 %y, %x816  %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)817  %s = sub i8 %a, %m818  ret i8 %s819}820 821define <2 x i8> @sub_add_umin_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {822; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_vec823; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> [[Z:%.*]]) {824; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[Y]], <2 x i8> [[Z]])825; CHECK-NEXT:    [[S:%.*]] = add <2 x i8> [[X]], [[TMP1]]826; CHECK-NEXT:    ret <2 x i8> [[S]]827;828  %a = add <2 x i8> %x, %y829  %m = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %y, <2 x i8> %z)830  %s = sub <2 x i8> %a, %m831  ret <2 x i8> %s832}833 834; negative test835 836define i8 @sub_add_umin_mismatch(i8 %x, i8 %y, i8 %z, i8 %t) {837; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_mismatch838; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[T:%.*]]) {839; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]840; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[T]], i8 [[Z]])841; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]842; CHECK-NEXT:    ret i8 [[S]]843;844  %a = add i8 %x, %y845  %m = call i8 @llvm.umin.i8(i8 %t, i8 %z)846  %s = sub i8 %a, %m847  ret i8 %s848}849 850define i8 @sub_add_umin_use_a(i8 %x, i8 %y, i8 %z) {851; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_a852; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {853; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]854; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])855; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]856; CHECK-NEXT:    call void @use8(i8 [[A]])857; CHECK-NEXT:    ret i8 [[S]]858;859  %a = add i8 %x, %y860  %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)861  %s = sub i8 %a, %m862  call void @use8(i8 %a)863  ret i8 %s864}865 866define i8 @sub_add_umin_use_m(i8 %x, i8 %y, i8 %z) {867; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_m868; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {869; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]870; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])871; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]872; CHECK-NEXT:    call void @use8(i8 [[M]])873; CHECK-NEXT:    ret i8 [[S]]874;875  %a = add i8 %x, %y876  %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)877  %s = sub i8 %a, %m878  call void @use8(i8 %m)879  ret i8 %s880}881 882define <2 x i8> @sub_smax0_sub_nsw(<2 x i8> %x, <2 x i8> %y) {883; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw884; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {885; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.smin.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])886; CHECK-NEXT:    ret <2 x i8> [[R]]887;888  %sub = sub nsw <2 x i8> %x, %y889  %m = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %sub, <2 x i8> <i8 0, i8 poison>)890  %r = sub <2 x i8> %x, %m891  ret <2 x i8> %r892}893 894define i8 @sub_smax0_sub_nsw_use(i8 %x, i8 %y) {895; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw_use896; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {897; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]898; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)899; CHECK-NEXT:    call void @use8(i8 [[M]])900; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])901; CHECK-NEXT:    ret i8 [[R]]902;903  %sub = sub nsw i8 %x, %y904  %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)905  call void @use8(i8 %m)906  %r = sub i8 %x, %m907  ret i8 %r908}909 910; negative test - must have nsw911 912define i8 @sub_smax0_sub(i8 %x, i8 %y) {913; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub914; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {915; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X]], [[Y]]916; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)917; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]918; CHECK-NEXT:    ret i8 [[R]]919;920  %sub = sub i8 %x, %y921  %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)922  %r = sub i8 %x, %m923  ret i8 %r924}925 926; negative test - wrong op927 928define i8 @sub_smax0_sub_commute(i8 %x, i8 %y) {929; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_commute930; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {931; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]932; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)933; CHECK-NEXT:    [[R:%.*]] = sub i8 [[M]], [[X]]934; CHECK-NEXT:    ret i8 [[R]]935;936  %sub = sub nsw i8 %x, %y937  %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)938  %r = sub i8 %m, %x939  ret i8 %r940}941 942define i8 @sub_smin0_sub_nsw_use(i8 %x, i8 %y) {943; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_use944; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {945; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]946; CHECK-NEXT:    call void @use8(i8 [[SUB]])947; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])948; CHECK-NEXT:    ret i8 [[R]]949;950  %sub = sub nsw i8 %x, %y951  call void @use8(i8 %sub)952  %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)953  %r = sub i8 %x, %m954  ret i8 %r955}956 957define <2 x i8> @sub_smin0_sub_nsw(<2 x i8> %x, <2 x i8> %y) {958; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw959; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {960; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])961; CHECK-NEXT:    ret <2 x i8> [[R]]962;963  %sub = sub nsw <2 x i8> %x, %y964  %m = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %sub, <2 x i8> zeroinitializer)965  %r = sub <2 x i8> %x, %m966  ret <2 x i8> %r967}968 969; negative test - must have nsw970 971define i8 @sub_smin0_sub(i8 %x, i8 %y) {972; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub973; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {974; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X]], [[Y]]975; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[SUB]], i8 0)976; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]977; CHECK-NEXT:    ret i8 [[R]]978;979  %sub = sub i8 %x, %y980  %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)981  %r = sub i8 %x, %m982  ret i8 %r983}984 985; negative test - wrong op986 987define i8 @sub_smin0_sub_nsw_commute(i8 %x, i8 %y) {988; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_commute989; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {990; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[Y]], [[X]]991; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[SUB]], i8 0)992; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]993; CHECK-NEXT:    ret i8 [[R]]994;995  %sub = sub nsw i8 %y, %x996  %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)997  %r = sub i8 %x, %m998  ret i8 %r999}1000 1001define i8 @sub_max_min_nsw(i8 %a, i8 %b) {1002; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw1003; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {1004; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]1005; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)1006; CHECK-NEXT:    ret i8 [[AB]]1007;1008  %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)1009  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)1010  %ab = sub nsw i8 %max, %min1011  ret i8 %ab1012}1013 1014define i8 @sub_max_min_nuw(i8 %a, i8 %b) {1015; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw1016; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {1017; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]1018; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)1019; CHECK-NEXT:    ret i8 [[AB]]1020;1021  %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)1022  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)1023  %ab = sub nuw i8 %max, %min1024  ret i8 %ab1025}1026 1027define i8 @sub_max_min_nsw_commute(i8 %a, i8 %b) {1028; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw_commute1029; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {1030; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]1031; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)1032; CHECK-NEXT:    ret i8 [[AB]]1033;1034  %min = call i8 @llvm.smin.i8(i8 %b, i8 %a)1035  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)1036  %ab = sub nsw i8 %max, %min1037  ret i8 %ab1038}1039 1040define i8 @sub_max_min_nuw_commute(i8 %a, i8 %b) {1041; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw_commute1042; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {1043; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]1044; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)1045; CHECK-NEXT:    ret i8 [[AB]]1046;1047  %min = call i8 @llvm.smin.i8(i8 %b, i8 %a)1048  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)1049  %ab = sub nuw i8 %max, %min1050  ret i8 %ab1051}1052 1053define <2 x i8> @sub_max_min_vec_nsw(<2 x i8> %a, <2 x i8> %b) {1054; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nsw1055; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {1056; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]1057; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)1058; CHECK-NEXT:    ret <2 x i8> [[AB]]1059;1060  %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)1061  %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)1062  %ab = sub nsw <2 x i8> %max, %min1063  ret <2 x i8> %ab1064}1065 1066define <2 x i8> @sub_max_min_vec_nuw(<2 x i8> %a, <2 x i8> %b) {1067; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nuw1068; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {1069; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]1070; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)1071; CHECK-NEXT:    ret <2 x i8> [[AB]]1072;1073  %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)1074  %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)1075  %ab = sub nuw <2 x i8> %max, %min1076  ret <2 x i8> %ab1077}1078 1079define <2 x i8> @sub_max_min_vec_nsw_commute(<2 x i8> %a, <2 x i8> %b) {1080; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nsw_commute1081; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {1082; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]1083; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)1084; CHECK-NEXT:    ret <2 x i8> [[AB]]1085;1086  %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %b, <2 x i8> %a)1087  %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)1088  %ab = sub nsw <2 x i8> %max, %min1089  ret <2 x i8> %ab1090}1091 1092define <2 x i8> @sub_max_min_vec_nuw_commute(<2 x i8> %a, <2 x i8> %b) {1093; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nuw_commute1094; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {1095; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]1096; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)1097; CHECK-NEXT:    ret <2 x i8> [[AB]]1098;1099  %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %b, <2 x i8> %a)1100  %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)1101  %ab = sub nuw <2 x i8> %max, %min1102  ret <2 x i8> %ab1103}1104 1105; negative test - multiple use1106 1107define i8 @sub_max_min_multi_use(i8 %a, i8 %b) {1108; CHECK-LABEL: define {{[^@]+}}@sub_max_min_multi_use1109; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {1110; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 [[B]])1111; CHECK-NEXT:    call void @use8(i8 [[MIN]])1112; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]])1113; CHECK-NEXT:    call void @use8(i8 [[MAX]])1114; CHECK-NEXT:    [[AB:%.*]] = sub nsw i8 [[MAX]], [[MIN]]1115; CHECK-NEXT:    ret i8 [[AB]]1116;1117  %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)1118  call void @use8(i8 %min)1119  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)1120  call void @use8(i8 %max)1121  %ab = sub nsw i8 %max, %min1122  ret i8 %ab1123}1124 1125define <2 x i8> @sub_max_min_vec_multi_use(<2 x i8> %a, <2 x i8> %b) {1126; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_multi_use1127; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {1128; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i8> @llvm.smin.v2i8(<2 x i8> [[A]], <2 x i8> [[B]])1129; CHECK-NEXT:    call void @use8v2(<2 x i8> [[MIN]])1130; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[A]], <2 x i8> [[B]])1131; CHECK-NEXT:    call void @use8v2(<2 x i8> [[MAX]])1132; CHECK-NEXT:    [[AB:%.*]] = sub nsw <2 x i8> [[MAX]], [[MIN]]1133; CHECK-NEXT:    ret <2 x i8> [[AB]]1134;1135  %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)1136  call void @use8v2(<2 x i8> %min)1137  %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)1138  call void @use8v2(<2 x i8> %max)1139  %ab = sub nsw <2 x i8> %max, %min1140  ret <2 x i8> %ab1141}1142 1143declare void @use8(i8)1144declare void @use32(i32 %u)1145 1146declare void @use8v2(i8)1147