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