1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4; Canonicalization of unsigned saturated subtraction idioms to 5; usub.sat() intrinsics is tested here. 6 7declare void @use(i64) 8declare void @usei32(i32) 9declare void @usei1(i1) 10 11; (a > b) ? a - b : 0 -> usub.sat(a, b) 12 13define i64 @max_sub_ugt(i64 %a, i64 %b) { 14; CHECK-LABEL: @max_sub_ugt( 15; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 16; CHECK-NEXT: ret i64 [[TMP1]] 17; 18 %cmp = icmp ugt i64 %a, %b 19 %sub = sub i64 %a, %b 20 %sel = select i1 %cmp, i64 %sub ,i64 0 21 ret i64 %sel 22} 23 24; (a >= b) ? a - b : 0 -> usub.sat(a, b) 25 26define i64 @max_sub_uge(i64 %a, i64 %b) { 27; CHECK-LABEL: @max_sub_uge( 28; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 29; CHECK-NEXT: ret i64 [[TMP1]] 30; 31 %cmp = icmp uge i64 %a, %b 32 %sub = sub i64 %a, %b 33 %sel = select i1 %cmp, i64 %sub ,i64 0 34 ret i64 %sel 35} 36 37define i64 @max_sub_uge_extrause1(i64 %a, i64 %b) { 38; CHECK-LABEL: @max_sub_uge_extrause1( 39; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]] 40; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) 41; CHECK-NEXT: call void @use(i64 [[SUB]]) 42; CHECK-NEXT: ret i64 [[TMP1]] 43; 44 %cmp = icmp uge i64 %a, %b 45 %sub = sub i64 %a, %b 46 %sel = select i1 %cmp, i64 %sub ,i64 0 47 call void @use(i64 %sub) 48 ret i64 %sel 49} 50 51define i64 @max_sub_uge_extrause2(i64 %a, i64 %b) { 52; CHECK-LABEL: @max_sub_uge_extrause2( 53; CHECK-NEXT: [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]] 54; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) 55; CHECK-NEXT: call void @usei1(i1 [[CMP]]) 56; CHECK-NEXT: ret i64 [[TMP1]] 57; 58 %cmp = icmp uge i64 %a, %b 59 %sub = sub i64 %a, %b 60 %sel = select i1 %cmp, i64 %sub ,i64 0 61 call void @usei1(i1 %cmp) 62 ret i64 %sel 63} 64 65define i64 @max_sub_uge_extrause3(i64 %a, i64 %b) { 66; CHECK-LABEL: @max_sub_uge_extrause3( 67; CHECK-NEXT: [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]] 68; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A]], [[B]] 69; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) 70; CHECK-NEXT: call void @use(i64 [[SUB]]) 71; CHECK-NEXT: call void @usei1(i1 [[CMP]]) 72; CHECK-NEXT: ret i64 [[TMP1]] 73; 74 %cmp = icmp uge i64 %a, %b 75 %sub = sub i64 %a, %b 76 %sel = select i1 %cmp, i64 %sub ,i64 0 77 call void @use(i64 %sub) 78 call void @usei1(i1 %cmp) 79 ret i64 %sel 80} 81 82; Again, with vectors: 83; (a > b) ? a - b : 0 -> usub.sat(a, b) 84 85define <4 x i32> @max_sub_ugt_vec(<4 x i32> %a, <4 x i32> %b) { 86; CHECK-LABEL: @max_sub_ugt_vec( 87; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) 88; CHECK-NEXT: ret <4 x i32> [[TMP1]] 89; 90 %cmp = icmp ugt <4 x i32> %a, %b 91 %sub = sub <4 x i32> %a, %b 92 %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer 93 ret <4 x i32> %sel 94} 95 96; Use extra ops to thwart icmp swapping canonicalization. 97; (b < a) ? a - b : 0 -> usub.sat(a, b) 98 99define i64 @max_sub_ult(i64 %a, i64 %b) { 100; CHECK-LABEL: @max_sub_ult( 101; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 102; CHECK-NEXT: [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]] 103; CHECK-NEXT: call void @use(i64 [[EXTRASUB]]) 104; CHECK-NEXT: ret i64 [[TMP1]] 105; 106 %cmp = icmp ult i64 %b, %a 107 %sub = sub i64 %a, %b 108 %sel = select i1 %cmp, i64 %sub ,i64 0 109 %extrasub = sub i64 %b, %a 110 call void @use(i64 %extrasub) 111 ret i64 %sel 112} 113 114; (b > a) ? 0 : a - b -> usub.sat(a, b) 115 116define i64 @max_sub_ugt_sel_swapped(i64 %a, i64 %b) { 117; CHECK-LABEL: @max_sub_ugt_sel_swapped( 118; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 119; CHECK-NEXT: [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]] 120; CHECK-NEXT: call void @use(i64 [[EXTRASUB]]) 121; CHECK-NEXT: ret i64 [[TMP1]] 122; 123 %cmp = icmp ugt i64 %b, %a 124 %sub = sub i64 %a, %b 125 %sel = select i1 %cmp, i64 0 ,i64 %sub 126 %extrasub = sub i64 %b, %a 127 call void @use(i64 %extrasub) 128 ret i64 %sel 129} 130 131; (a < b) ? 0 : a - b -> usub.sat(a, b) 132 133define i64 @max_sub_ult_sel_swapped(i64 %a, i64 %b) { 134; CHECK-LABEL: @max_sub_ult_sel_swapped( 135; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 136; CHECK-NEXT: ret i64 [[TMP1]] 137; 138 %cmp = icmp ult i64 %a, %b 139 %sub = sub i64 %a, %b 140 %sel = select i1 %cmp, i64 0 ,i64 %sub 141 ret i64 %sel 142} 143 144; ((a > b) ? b - a : 0) -> -usub.sat(a, b) 145 146define i64 @neg_max_sub_ugt(i64 %a, i64 %b) { 147; CHECK-LABEL: @neg_max_sub_ugt( 148; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 149; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 150; CHECK-NEXT: [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]] 151; CHECK-NEXT: call void @use(i64 [[EXTRASUB]]) 152; CHECK-NEXT: ret i64 [[TMP2]] 153; 154 %cmp = icmp ugt i64 %a, %b 155 %sub = sub i64 %b, %a 156 %sel = select i1 %cmp, i64 %sub ,i64 0 157 %extrasub = sub i64 %a, %b 158 call void @use(i64 %extrasub) 159 ret i64 %sel 160} 161 162; ((b < a) ? b - a : 0) -> -usub.sat(a, b) 163 164define i64 @neg_max_sub_ult(i64 %a, i64 %b) { 165; CHECK-LABEL: @neg_max_sub_ult( 166; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 167; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 168; CHECK-NEXT: ret i64 [[TMP2]] 169; 170 %cmp = icmp ult i64 %b, %a 171 %sub = sub i64 %b, %a 172 %sel = select i1 %cmp, i64 %sub ,i64 0 173 ret i64 %sel 174} 175 176; ((b > a) ? 0 : b - a) -> -usub.sat(a, b) 177 178define i64 @neg_max_sub_ugt_sel_swapped(i64 %a, i64 %b) { 179; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped( 180; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 181; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 182; CHECK-NEXT: ret i64 [[TMP2]] 183; 184 %cmp = icmp ugt i64 %b, %a 185 %sub = sub i64 %b, %a 186 %sel = select i1 %cmp, i64 0 ,i64 %sub 187 ret i64 %sel 188} 189 190define i64 @neg_max_sub_ugt_sel_swapped_extrause1(i64 %a, i64 %b) { 191; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause1( 192; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]] 193; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) 194; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 195; CHECK-NEXT: call void @usei1(i1 [[CMP]]) 196; CHECK-NEXT: ret i64 [[TMP2]] 197; 198 %cmp = icmp ugt i64 %b, %a 199 %sub = sub i64 %b, %a 200 %sel = select i1 %cmp, i64 0 ,i64 %sub 201 call void @usei1(i1 %cmp) 202 ret i64 %sel 203} 204 205define i64 @neg_max_sub_ugt_sel_swapped_extrause2(i64 %a, i64 %b) { 206; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause2( 207; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[B:%.*]], [[A:%.*]] 208; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) 209; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 210; CHECK-NEXT: call void @use(i64 [[SUB]]) 211; CHECK-NEXT: ret i64 [[TMP2]] 212; 213 %cmp = icmp ugt i64 %b, %a 214 %sub = sub i64 %b, %a 215 %sel = select i1 %cmp, i64 0 ,i64 %sub 216 call void @use(i64 %sub) 217 ret i64 %sel 218} 219 220define i64 @neg_max_sub_ugt_sel_swapped_extrause3(i64 %a, i64 %b) { 221; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause3( 222; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]] 223; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[B]], [[A]] 224; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i64 0, i64 [[SUB]] 225; CHECK-NEXT: call void @use(i64 [[SUB]]) 226; CHECK-NEXT: call void @usei1(i1 [[CMP]]) 227; CHECK-NEXT: ret i64 [[SEL]] 228; 229 %cmp = icmp ugt i64 %b, %a 230 %sub = sub i64 %b, %a 231 %sel = select i1 %cmp, i64 0 ,i64 %sub 232 call void @use(i64 %sub) 233 call void @usei1(i1 %cmp) 234 ret i64 %sel 235} 236 237; ((a < b) ? 0 : b - a) -> -usub.sat(a, b) 238 239define i64 @neg_max_sub_ult_sel_swapped(i64 %a, i64 %b) { 240; CHECK-LABEL: @neg_max_sub_ult_sel_swapped( 241; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 242; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] 243; CHECK-NEXT: [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]] 244; CHECK-NEXT: call void @use(i64 [[EXTRASUB]]) 245; CHECK-NEXT: ret i64 [[TMP2]] 246; 247 %cmp = icmp ult i64 %a, %b 248 %sub = sub i64 %b, %a 249 %sel = select i1 %cmp, i64 0 ,i64 %sub 250 %extrasub = sub i64 %a, %b 251 call void @use(i64 %extrasub) 252 ret i64 %sel 253} 254 255define i32 @max_sub_ugt_c1(i32 %a) { 256; CHECK-LABEL: @max_sub_ugt_c1( 257; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1) 258; CHECK-NEXT: ret i32 [[TMP1]] 259; 260 %cmp = icmp ugt i32 %a, 1 261 %sub = add i32 %a, -1 262 %sel = select i1 %cmp, i32 %sub ,i32 0 263 ret i32 %sel 264} 265 266define i32 @max_sub_ugt_c01(i32 %a) { 267; CHECK-LABEL: @max_sub_ugt_c01( 268; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 269; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -1 270; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 0, i32 [[SUB]] 271; CHECK-NEXT: ret i32 [[SEL]] 272; 273 %cmp = icmp ugt i32 %a, 0 274 %sub = add i32 %a, -1 275 %sel = select i1 %cmp, i32 %sub ,i32 0 276 ret i32 %sel 277} 278 279define i32 @max_sub_ugt_c10(i32 %a) { 280; CHECK-LABEL: @max_sub_ugt_c10( 281; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10) 282; CHECK-NEXT: ret i32 [[TMP1]] 283; 284 %cmp = icmp ugt i32 %a, 10 285 %sub = add i32 %a, -10 286 %sel = select i1 %cmp, i32 %sub, i32 0 287 ret i32 %sel 288} 289 290define i32 @max_sub_ugt_c910(i32 %a) { 291; CHECK-LABEL: @max_sub_ugt_c910( 292; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 9 293; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -10 294; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 295; CHECK-NEXT: ret i32 [[SEL]] 296; 297 %cmp = icmp ugt i32 %a, 9 298 %sub = add i32 %a, -10 299 %sel = select i1 %cmp, i32 %sub, i32 0 300 ret i32 %sel 301} 302 303define i32 @max_sub_ugt_c1110(i32 %a) { 304; CHECK-LABEL: @max_sub_ugt_c1110( 305; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 11 306; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -10 307; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 308; CHECK-NEXT: ret i32 [[SEL]] 309; 310 %cmp = icmp ugt i32 %a, 11 311 %sub = add i32 %a, -10 312 %sel = select i1 %cmp, i32 %sub, i32 0 313 ret i32 %sel 314} 315 316define i32 @max_sub_ugt_c0(i32 %a) { 317; CHECK-LABEL: @max_sub_ugt_c0( 318; CHECK-NEXT: ret i32 0 319; 320 %cmp = icmp ugt i32 %a, -1 321 %sub = add i32 %a, 0 322 %sel = select i1 %cmp, i32 %sub, i32 0 323 ret i32 %sel 324} 325 326define i32 @max_sub_ugt_cmiss(i32 %a) { 327; CHECK-LABEL: @max_sub_ugt_cmiss( 328; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 1 329; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2 330; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 331; CHECK-NEXT: ret i32 [[SEL]] 332; 333 %cmp = icmp ugt i32 %a, 1 334 %sub = add i32 %a, -2 335 %sel = select i1 %cmp, i32 %sub, i32 0 336 ret i32 %sel 337} 338 339define i32 @max_sub_ult_c1(i32 %a) { 340; CHECK-LABEL: @max_sub_ult_c1( 341; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 342; CHECK-NEXT: [[SEL:%.*]] = sext i1 [[CMP]] to i32 343; CHECK-NEXT: ret i32 [[SEL]] 344; 345 %cmp = icmp ult i32 %a, 1 346 %sub = add i32 %a, -1 347 %sel = select i1 %cmp, i32 %sub, i32 0 348 ret i32 %sel 349} 350 351define i32 @max_sub_ult_c2(i32 %a) { 352; CHECK-LABEL: @max_sub_ult_c2( 353; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]]) 354; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] 355; CHECK-NEXT: ret i32 [[TMP2]] 356; 357 %cmp = icmp ult i32 %a, 2 358 %sub = add i32 %a, -2 359 %sel = select i1 %cmp, i32 %sub, i32 0 360 ret i32 %sel 361} 362 363define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) { 364; CHECK-LABEL: @max_sub_ult_c2_oneuseicmp( 365; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2 366; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]]) 367; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] 368; CHECK-NEXT: call void @usei1(i1 [[CMP]]) 369; CHECK-NEXT: ret i32 [[TMP2]] 370; 371 %cmp = icmp ult i32 %a, 2 372 %sub = add i32 %a, -2 373 %sel = select i1 %cmp, i32 %sub, i32 0 374 call void @usei1(i1 %cmp) 375 ret i32 %sel 376} 377 378define i32 @max_sub_ult_c2_oneusesub(i32 %a) { 379; CHECK-LABEL: @max_sub_ult_c2_oneusesub( 380; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A:%.*]], -2 381; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]]) 382; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] 383; CHECK-NEXT: call void @usei32(i32 [[SUB]]) 384; CHECK-NEXT: ret i32 [[TMP2]] 385; 386 %cmp = icmp ult i32 %a, 2 387 %sub = add i32 %a, -2 388 %sel = select i1 %cmp, i32 %sub, i32 0 389 call void @usei32(i32 %sub) 390 ret i32 %sel 391} 392 393define i32 @max_sub_ult_c32(i32 %a) { 394; CHECK-LABEL: @max_sub_ult_c32( 395; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3 396; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2 397; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 398; CHECK-NEXT: ret i32 [[SEL]] 399; 400 %cmp = icmp ult i32 %a, 3 401 %sub = add i32 %a, -2 402 %sel = select i1 %cmp, i32 %sub, i32 0 403 ret i32 %sel 404} 405 406define i32 @max_sub_ugt_c32(i32 %a) { 407; CHECK-LABEL: @max_sub_ugt_c32( 408; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3 409; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2 410; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 411; CHECK-NEXT: ret i32 [[SEL]] 412; 413 %cmp = icmp ugt i32 3, %a 414 %sub = add i32 %a, -2 415 %sel = select i1 %cmp, i32 %sub, i32 0 416 ret i32 %sel 417} 418 419define i32 @max_sub_uge_c32(i32 %a) { 420; CHECK-LABEL: @max_sub_uge_c32( 421; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3 422; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2 423; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0 424; CHECK-NEXT: ret i32 [[SEL]] 425; 426 %cmp = icmp uge i32 2, %a 427 %sub = add i32 %a, -2 428 %sel = select i1 %cmp, i32 %sub, i32 0 429 ret i32 %sel 430} 431 432define i32 @max_sub_ult_c12(i32 %a) { 433; CHECK-LABEL: @max_sub_ult_c12( 434; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 435; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -2, i32 0 436; CHECK-NEXT: ret i32 [[SEL]] 437; 438 %cmp = icmp ult i32 %a, 1 439 %sub = add i32 %a, -2 440 %sel = select i1 %cmp, i32 %sub, i32 0 441 ret i32 %sel 442} 443 444define i32 @max_sub_ult_c0(i32 %a) { 445; CHECK-LABEL: @max_sub_ult_c0( 446; CHECK-NEXT: ret i32 0 447; 448 %cmp = icmp ult i32 %a, 0 449 %sub = add i32 %a, -1 450 %sel = select i1 %cmp, i32 %sub, i32 0 451 ret i32 %sel 452} 453 454