1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 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_na 17; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 18; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 19; 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, -1 24 %l0 = icmp ult i32 %not, %B 25 %l1 = select i1 %l0, i32 %not, i32 %B 26 %x = sub i32 %l1, %not 27 ret i32 %x 28} 29 30define i32 @na_minus_max_na_b(i32 %A, i32 %B) { 31; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_b 32; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 33; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 34; 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, -1 38 %l0 = icmp ult i32 %not, %B 39 %l1 = select i1 %l0, i32 %not, i32 %B 40 %x = sub i32 %not, %l1 41 ret i32 %x 42} 43 44define i5 @sub_umin(i5 %a, i5 %b) { 45; CHECK-LABEL: define {{[^@]+}}@sub_umin 46; 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, %umin 52 ret i5 %r 53} 54 55define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) { 56; CHECK-LABEL: define {{[^@]+}}@sub_umin_commute_vec 57; 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, %umin 63 ret <2 x i8> %r 64} 65 66define i5 @sub_umin_uses(i5 %a, i5 %b, ptr %p) { 67; CHECK-LABEL: define {{[^@]+}}@sub_umin_uses 68; 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 1 71; 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 %p 76 %r = sub i5 %a, %umin 77 ret i5 %r 78} 79 80define i5 @sub_umin_no_common_op(i5 %a, i5 %b, i5 %c) { 81; CHECK-LABEL: define {{[^@]+}}@sub_umin_no_common_op 82; 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, %umin 89 ret i5 %r 90} 91 92define i32 @max_b_na_minus_na(i32 %A, i32 %B) { 93; CHECK-LABEL: define {{[^@]+}}@max_b_na_minus_na 94; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 95; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 96; 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, -1 101 %l0 = icmp ugt i32 %not, %B 102 %l1 = select i1 %l0, i32 %B, i32 %not 103 %x = sub i32 %l1, %not 104 ret i32 %x 105} 106 107define i32 @na_minus_max_b_na(i32 %A, i32 %B) { 108; CHECK-LABEL: define {{[^@]+}}@na_minus_max_b_na 109; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 110; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 111; 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, -1 115 %l0 = icmp ugt i32 %not, %B 116 %l1 = select i1 %l0, i32 %B, i32 %not 117 %x = sub i32 %not, %l1 118 ret i32 %x 119} 120 121 122define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) { 123; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na 124; 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, -1 130 %not = xor i32 %A, -1 131 %l0 = icmp ult i32 %not, %B 132 %l1 = select i1 %l0, i32 %not, i32 %B 133 %x = sub i32 %l1, %not 134 ret i32 %x 135} 136 137define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) { 138; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi 139; 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, -1 144 %not = xor i32 %A, -1 145 %l0 = icmp ult i32 %not, %B 146 %l1 = select i1 %l0, i32 %not, i32 %B 147 %x = sub i32 %not, %l1 148 ret i32 %x 149} 150 151define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) { 152; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na 153; 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, -1 159 %not = xor i32 %A, -1 160 %l0 = icmp ugt i32 %not, %B 161 %l1 = select i1 %l0, i32 %B, i32 %not 162 %x = sub i32 %l1, %not 163 ret i32 %x 164} 165 166define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) { 167; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na 168; 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, -1 173 %not = xor i32 %A, -1 174 %l0 = icmp ugt i32 %not, %B 175 %l1 = select i1 %l0, i32 %B, i32 %not 176 %x = sub i32 %not, %l1 177 ret i32 %x 178} 179 180 181define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) { 182; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use 183; 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]], -1 186; 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, -1 191 %l0 = icmp ult i32 %not, 31 192 %l1 = select i1 %l0, i32 %not, i32 31 193 %x = sub i32 %l1, %not 194 call void @use32(i32 %l1) 195 ret i32 %x 196} 197 198define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) { 199; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use 200; 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]], -1 203; 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, -1 208 %l0 = icmp ult i32 %not, 31 209 %l1 = select i1 %l0, i32 %not, i32 31 210 %x = sub i32 %not, %l1 211 call void @use32(i32 %l1) 212 ret i32 %x 213} 214 215define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) { 216; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use 217; 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]], -1 220; 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, -1 225 %B = xor i32 %Bi, -1 226 %l0 = icmp ult i32 %B, %not 227 %l1 = select i1 %l0, i32 %B, i32 %not 228 %x = sub i32 %l1, %not 229 call void @use32(i32 %l1) 230 ret i32 %x 231} 232 233define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) { 234; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use 235; 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]], -1 238; 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, -1 243 %B = xor i32 %Bi, -1 244 %l0 = icmp ult i32 %B, %not 245 %l1 = select i1 %l0, i32 %B, i32 %not 246 %x = sub i32 %not, %l1 247 call void @use32(i32 %l1) 248 ret i32 %x 249} 250 251 252define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) { 253; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use2 254; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) { 255; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 256; 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, -1 263 %l0 = icmp ult i32 %not, 31 264 %l1 = select i1 %l0, i32 %not, i32 31 265 %x = sub i32 %l1, %not 266 call void @use32(i32 %l1) 267 call void @use32(i32 %not) 268 ret i32 %x 269} 270 271define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) { 272; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use2 273; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) { 274; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 275; 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, -1 282 %l0 = icmp ult i32 %not, 31 283 %l1 = select i1 %l0, i32 %not, i32 31 284 %x = sub i32 %not, %l1 285 call void @use32(i32 %l1) 286 call void @use32(i32 %not) 287 ret i32 %x 288} 289 290define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) { 291; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use2 292; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) { 293; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 294; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]]) 295; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP1]], -1 296; 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, -1 302 %B = xor i32 %Bi, -1 303 %l0 = icmp ult i32 %B, %not 304 %l1 = select i1 %l0, i32 %B, i32 %not 305 %x = sub i32 %l1, %not 306 call void @use32(i32 %l1) 307 call void @use32(i32 %not) 308 ret i32 %x 309} 310 311define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) { 312; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use2 313; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) { 314; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 315; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]]) 316; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP1]], -1 317; 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, -1 323 %B = xor i32 %Bi, -1 324 %l0 = icmp ult i32 %B, %not 325 %l1 = select i1 %l0, i32 %B, i32 %not 326 %x = sub i32 %not, %l1 327 call void @use32(i32 %l1) 328 call void @use32(i32 %not) 329 ret i32 %x 330} 331 332define i8 @umin_not_sub(i8 %x, i8 %y) { 333; CHECK-LABEL: define {{[^@]+}}@umin_not_sub 334; 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]], -1 337; 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, -1 344 %ny = xor i8 %y, -1 345 %cmpxy = icmp ult i8 %nx, %ny 346 %minxy = select i1 %cmpxy, i8 %nx, i8 %ny 347 %subx = sub i8 %nx, %minxy 348 %suby = sub i8 %ny, %minxy 349 call void @use8(i8 %subx) 350 call void @use8(i8 %suby) 351 ret i8 %minxy 352} 353 354define i8 @umin_not_sub_rev(i8 %x, i8 %y) { 355; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_rev 356; 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]], -1 359; 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, -1 366 %ny = xor i8 %y, -1 367 %cmpxy = icmp ult i8 %nx, %ny 368 %minxy = select i1 %cmpxy, i8 %nx, i8 %ny 369 %subx = sub i8 %minxy, %nx 370 %suby = sub i8 %minxy, %ny 371 call void @use8(i8 %subx) 372 call void @use8(i8 %suby) 373 ret i8 %minxy 374} 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_subs 378; 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]], -1 382; 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 void 390; 391 %xn = xor i8 %x, -1 392 %yn = xor i8 %y, -1 393 %zn = xor i8 %z, -1 394 %cmpxz = icmp ult i8 %xn, %zn 395 %minxz = select i1 %cmpxz, i8 %xn, i8 %zn 396 %cmpxyz = icmp ult i8 %minxz, %yn 397 %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn 398 %xmin = sub i8 %xn, %minxyz 399 %ymin = sub i8 %yn, %minxyz 400 %zmin = sub i8 %zn, %minxyz 401 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 void 406} 407 408; Handle this pattern with extra uses because it shows up in benchmarks. 409; ~X - Min/Max(~X, Y) -> ~Min/Max(X, ~Y) - X 410; ~X - Min/Max(Y, ~X) -> ~Min/Max(X, ~Y) - X 411; 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_commute0 416; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) { 417; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y]], -1 418; 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]], -1 421; 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, -1 426 %ny = xor i8 %y, -1 427 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, %m 431 ret i8 %subx 432} 433 434define i8 @umax_not_sub_intrinsic_commute1(i8 %x, i8 %y) { 435; CHECK-LABEL: define {{[^@]+}}@umax_not_sub_intrinsic_commute1 436; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) { 437; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y]], -1 438; 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]], -1 441; 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, -1 446 %ny = xor i8 %y, -1 447 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, %m 451 ret i8 %subx 452} 453 454define i8 @smin_not_sub_intrinsic_commute2(i8 %x, i8 %y) { 455; CHECK-LABEL: define {{[^@]+}}@smin_not_sub_intrinsic_commute2 456; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) { 457; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y]], -1 458; 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]], -1 461; 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, -1 466 %ny = xor i8 %y, -1 467 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, %nx 471 ret i8 %subx 472} 473 474define i8 @smax_not_sub_intrinsic_commute3(i8 %x, i8 %y) { 475; CHECK-LABEL: define {{[^@]+}}@smax_not_sub_intrinsic_commute3 476; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) { 477; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y]], -1 478; 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]], -1 481; 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, -1 486 %ny = xor i8 %y, -1 487 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, %nx 491 ret i8 %subx 492} 493 494; negative test - don't increase instruction count 495 496define i8 @umin_not_sub_intrinsic_uses(i8 %x, i8 %y) { 497; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_intrinsic_uses 498; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) { 499; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X]], -1 500; CHECK-NEXT: call void @use8(i8 [[NX]]) 501; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y]], -1 502; 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, -1 509 call void @use8(i8 %nx) 510 %ny = xor i8 %y, -1 511 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, %m 515 ret i8 %subx 516} 517 518define i8 @umax_sub_op0(i8 %x, i8 %y) { 519; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0 520; 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, %y 526 ret i8 %r 527} 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_commute 531; 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, %y 537 ret <2 x i8> %r 538} 539 540define i8 @umax_sub_op0_use(i8 %x, i8 %y) { 541; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0_use 542; 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, %y 551 ret i8 %r 552} 553 554define i8 @umax_sub_op1(i8 %x, i8 %y) { 555; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1 556; 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, %u 563 ret i8 %r 564} 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_commute 568; 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, %u 575 ret <2 x i8> %r 576} 577 578define i8 @umax_sub_op1_use(i8 %x, i8 %y) { 579; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1_use 580; 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, %u 589 ret i8 %r 590} 591 592define i8 @umin_sub_op1(i8 %x, i8 %y) { 593; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1 594; 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, %u 600 ret i8 %r 601} 602 603define i8 @umin_sub_op1_commute(i8 %x, i8 %y) { 604; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_commute 605; 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, %u 611 ret i8 %r 612} 613 614define i8 @umin_sub_op0(i8 %x, i8 %y) { 615; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0 616; 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, %y 623 ret i8 %r 624} 625 626define i8 @umin_sub_op0_commute(i8 %x, i8 %y) { 627; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_commute 628; 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, %y 635 ret i8 %r 636} 637 638define i8 @umin_sub_op1_use(i8 %x, i8 %y) { 639; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_use 640; 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, %u 649 ret i8 %r 650} 651 652define i8 @umin_sub_op0_use(i8 %x, i8 %y) { 653; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_use 654; 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, %y 663 ret i8 %r 664} 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_smin 673; 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, %y 678 %m = call i8 @llvm.smin.i8(i8 %x, i8 %y) 679 %s = sub i8 %a, %m 680 ret i8 %s 681} 682 683define i8 @diff_add_smax(i8 %x, i8 %y) { 684; CHECK-LABEL: define {{[^@]+}}@diff_add_smax 685; 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, %y 690 %m = call i8 @llvm.smax.i8(i8 %y, i8 %x) 691 %s = sub i8 %a, %m 692 ret i8 %s 693} 694 695define i8 @diff_add_umin(i8 %x, i8 %y) { 696; CHECK-LABEL: define {{[^@]+}}@diff_add_umin 697; 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, %y 702 %m = call i8 @llvm.umin.i8(i8 %x, i8 %y) 703 %s = sub i8 %a, %m 704 ret i8 %s 705} 706 707define i8 @diff_add_umax(i8 %x, i8 %y) { 708; CHECK-LABEL: define {{[^@]+}}@diff_add_umax 709; 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, %y 714 %m = call i8 @llvm.umax.i8(i8 %y, i8 %x) 715 %s = sub i8 %a, %m 716 ret i8 %s 717} 718 719define i8 @diff_add_smin_use(i8 %x, i8 %y) { 720; CHECK-LABEL: define {{[^@]+}}@diff_add_smin_use 721; 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, %y 728 %m = call i8 @llvm.smin.i8(i8 %x, i8 %y) 729 %s = sub i8 %a, %m 730 call void @use8(i8 %m) 731 ret i8 %s 732} 733 734define i8 @diff_add_use_smax(i8 %x, i8 %y) { 735; CHECK-LABEL: define {{[^@]+}}@diff_add_use_smax 736; 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, %y 743 %m = call i8 @llvm.smax.i8(i8 %y, i8 %x) 744 %s = sub i8 %a, %m 745 call void @use8(i8 %a) 746 ret i8 %s 747} 748 749define i8 @diff_add_use_umin_use(i8 %x, i8 %y) { 750; CHECK-LABEL: define {{[^@]+}}@diff_add_use_umin_use 751; 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, %y 760 %m = call i8 @llvm.umin.i8(i8 %x, i8 %y) 761 %s = sub i8 %a, %m 762 call void @use8(i8 %a) 763 call void @use8(i8 %m) 764 ret i8 %s 765} 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_umin 771; 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, %y 777 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z) 778 %s = sub i8 %a, %m 779 ret i8 %s 780} 781 782define i8 @sub_add_umin_commute_umin(i8 %x, i8 %y, i8 %z) { 783; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_umin 784; 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, %y 790 %m = call i8 @llvm.umin.i8(i8 %z, i8 %y) 791 %s = sub i8 %a, %m 792 ret i8 %s 793} 794 795define i8 @sub_add_umin_commute_add(i8 %x, i8 %y, i8 %z) { 796; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add 797; 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, %x 803 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z) 804 %s = sub i8 %a, %m 805 ret i8 %s 806} 807 808define i8 @sub_add_umin_commute_add_umin(i8 %x, i8 %y, i8 %z) { 809; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add_umin 810; 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, %x 816 %m = call i8 @llvm.umin.i8(i8 %z, i8 %y) 817 %s = sub i8 %a, %m 818 ret i8 %s 819} 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_vec 823; 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, %y 829 %m = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %y, <2 x i8> %z) 830 %s = sub <2 x i8> %a, %m 831 ret <2 x i8> %s 832} 833 834; negative test 835 836define i8 @sub_add_umin_mismatch(i8 %x, i8 %y, i8 %z, i8 %t) { 837; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_mismatch 838; 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, %y 845 %m = call i8 @llvm.umin.i8(i8 %t, i8 %z) 846 %s = sub i8 %a, %m 847 ret i8 %s 848} 849 850define i8 @sub_add_umin_use_a(i8 %x, i8 %y, i8 %z) { 851; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_a 852; 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, %y 860 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z) 861 %s = sub i8 %a, %m 862 call void @use8(i8 %a) 863 ret i8 %s 864} 865 866define i8 @sub_add_umin_use_m(i8 %x, i8 %y, i8 %z) { 867; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_m 868; 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, %y 876 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z) 877 %s = sub i8 %a, %m 878 call void @use8(i8 %m) 879 ret i8 %s 880} 881 882define <2 x i8> @sub_smax0_sub_nsw(<2 x i8> %x, <2 x i8> %y) { 883; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw 884; 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, %y 889 %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, %m 891 ret <2 x i8> %r 892} 893 894define i8 @sub_smax0_sub_nsw_use(i8 %x, i8 %y) { 895; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw_use 896; 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, %y 904 %m = call i8 @llvm.smax.i8(i8 %sub, i8 0) 905 call void @use8(i8 %m) 906 %r = sub i8 %x, %m 907 ret i8 %r 908} 909 910; negative test - must have nsw 911 912define i8 @sub_smax0_sub(i8 %x, i8 %y) { 913; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub 914; 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, %y 921 %m = call i8 @llvm.smax.i8(i8 %sub, i8 0) 922 %r = sub i8 %x, %m 923 ret i8 %r 924} 925 926; negative test - wrong op 927 928define i8 @sub_smax0_sub_commute(i8 %x, i8 %y) { 929; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_commute 930; 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, %y 937 %m = call i8 @llvm.smax.i8(i8 %sub, i8 0) 938 %r = sub i8 %m, %x 939 ret i8 %r 940} 941 942define i8 @sub_smin0_sub_nsw_use(i8 %x, i8 %y) { 943; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_use 944; 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, %y 951 call void @use8(i8 %sub) 952 %m = call i8 @llvm.smin.i8(i8 %sub, i8 0) 953 %r = sub i8 %x, %m 954 ret i8 %r 955} 956 957define <2 x i8> @sub_smin0_sub_nsw(<2 x i8> %x, <2 x i8> %y) { 958; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw 959; 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, %y 964 %m = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %sub, <2 x i8> zeroinitializer) 965 %r = sub <2 x i8> %x, %m 966 ret <2 x i8> %r 967} 968 969; negative test - must have nsw 970 971define i8 @sub_smin0_sub(i8 %x, i8 %y) { 972; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub 973; 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, %y 980 %m = call i8 @llvm.smin.i8(i8 %sub, i8 0) 981 %r = sub i8 %x, %m 982 ret i8 %r 983} 984 985; negative test - wrong op 986 987define i8 @sub_smin0_sub_nsw_commute(i8 %x, i8 %y) { 988; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_commute 989; 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, %x 996 %m = call i8 @llvm.smin.i8(i8 %sub, i8 0) 997 %r = sub i8 %x, %m 998 ret i8 %r 999} 1000 1001define i8 @sub_max_min_nsw(i8 %a, i8 %b) { 1002; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw 1003; 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, %min 1011 ret i8 %ab 1012} 1013 1014define i8 @sub_max_min_nuw(i8 %a, i8 %b) { 1015; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw 1016; 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, %min 1024 ret i8 %ab 1025} 1026 1027define i8 @sub_max_min_nsw_commute(i8 %a, i8 %b) { 1028; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw_commute 1029; 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, %min 1037 ret i8 %ab 1038} 1039 1040define i8 @sub_max_min_nuw_commute(i8 %a, i8 %b) { 1041; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw_commute 1042; 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, %min 1050 ret i8 %ab 1051} 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_nsw 1055; 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, %min 1063 ret <2 x i8> %ab 1064} 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_nuw 1068; 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, %min 1076 ret <2 x i8> %ab 1077} 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_commute 1081; 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, %min 1089 ret <2 x i8> %ab 1090} 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_commute 1094; 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, %min 1102 ret <2 x i8> %ab 1103} 1104 1105; negative test - multiple use 1106 1107define i8 @sub_max_min_multi_use(i8 %a, i8 %b) { 1108; CHECK-LABEL: define {{[^@]+}}@sub_max_min_multi_use 1109; 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, %min 1122 ret i8 %ab 1123} 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_use 1127; 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, %min 1140 ret <2 x i8> %ab 1141} 1142 1143declare void @use8(i8) 1144declare void @use32(i32 %u) 1145 1146declare void @use8v2(i8) 1147