1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i32) 5declare void @use_vec(<2 x i8>) 6 7define i1 @test_nuw_and_unsigned_pred(i64 %x) { 8; CHECK-LABEL: @test_nuw_and_unsigned_pred( 9; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7 10; CHECK-NEXT: ret i1 [[Z]] 11; 12 %y = sub nuw i64 10, %x 13 %z = icmp ult i64 %y, 3 14 ret i1 %z 15} 16 17define i1 @test_nsw_and_signed_pred(i64 %x) { 18; CHECK-LABEL: @test_nsw_and_signed_pred( 19; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[X:%.*]], -7 20; CHECK-NEXT: ret i1 [[Z]] 21; 22 %y = sub nsw i64 3, %x 23 %z = icmp sgt i64 %y, 10 24 ret i1 %z 25} 26 27define i1 @test_nuw_nsw_and_unsigned_pred(i64 %x) { 28; CHECK-LABEL: @test_nuw_nsw_and_unsigned_pred( 29; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 6 30; CHECK-NEXT: ret i1 [[Z]] 31; 32 %y = sub nuw nsw i64 10, %x 33 %z = icmp ule i64 %y, 3 34 ret i1 %z 35} 36 37define i1 @test_nuw_nsw_and_signed_pred(i64 %x) { 38; CHECK-LABEL: @test_nuw_nsw_and_signed_pred( 39; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7 40; CHECK-NEXT: ret i1 [[Z]] 41; 42 %y = sub nuw nsw i64 10, %x 43 %z = icmp slt i64 %y, 3 44 ret i1 %z 45} 46 47define i1 @test_negative_nuw_and_signed_pred(i64 %x) { 48; CHECK-LABEL: @test_negative_nuw_and_signed_pred( 49; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7 50; CHECK-NEXT: ret i1 [[Z]] 51; 52 %y = sub nuw i64 10, %x 53 %z = icmp slt i64 %y, 3 54 ret i1 %z 55} 56 57define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) { 58; CHECK-LABEL: @test_negative_nsw_and_unsigned_pred( 59; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[X:%.*]], -8 60; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[TMP1]], 3 61; CHECK-NEXT: ret i1 [[Z]] 62; 63 %y = sub nsw i64 10, %x 64 %z = icmp ult i64 %y, 3 65 ret i1 %z 66} 67 68define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) { 69; CHECK-LABEL: @test_negative_combined_sub_unsigned_overflow( 70; CHECK-NEXT: ret i1 true 71; 72 %y = sub nuw i64 10, %x 73 %z = icmp ult i64 %y, 11 74 ret i1 %z 75} 76 77define i1 @test_negative_combined_sub_signed_overflow(i8 %x) { 78; CHECK-LABEL: @test_negative_combined_sub_signed_overflow( 79; CHECK-NEXT: ret i1 false 80; 81 %y = sub nsw i8 127, %x 82 %z = icmp slt i8 %y, -1 83 ret i1 %z 84} 85 86define i1 @test_sub_0_Y_eq_0(i8 %y) { 87; CHECK-LABEL: @test_sub_0_Y_eq_0( 88; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0 89; CHECK-NEXT: ret i1 [[Z]] 90; 91 %s = sub i8 0, %y 92 %z = icmp eq i8 %s, 0 93 ret i1 %z 94} 95 96define i1 @test_sub_0_Y_ne_0(i8 %y) { 97; CHECK-LABEL: @test_sub_0_Y_ne_0( 98; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[Y:%.*]], 0 99; CHECK-NEXT: ret i1 [[Z]] 100; 101 %s = sub i8 0, %y 102 %z = icmp ne i8 %s, 0 103 ret i1 %z 104} 105 106define i1 @test_sub_4_Y_ne_4(i8 %y) { 107; CHECK-LABEL: @test_sub_4_Y_ne_4( 108; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[Y:%.*]], 0 109; CHECK-NEXT: ret i1 [[Z]] 110; 111 %s = sub i8 4, %y 112 %z = icmp ne i8 %s, 4 113 ret i1 %z 114} 115 116define i1 @test_sub_127_Y_eq_127(i8 %y) { 117; CHECK-LABEL: @test_sub_127_Y_eq_127( 118; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0 119; CHECK-NEXT: ret i1 [[Z]] 120; 121 %s = sub i8 127, %y 122 %z = icmp eq i8 %s, 127 123 ret i1 %z 124} 125 126define i1 @test_sub_255_Y_eq_255(i8 %y) { 127; CHECK-LABEL: @test_sub_255_Y_eq_255( 128; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0 129; CHECK-NEXT: ret i1 [[Z]] 130; 131 %s = sub i8 255, %y 132 %z = icmp eq i8 %s, 255 133 ret i1 %z 134} 135define <2 x i1> @test_sub_255_Y_eq_255_vec(<2 x i8> %y) { 136; CHECK-LABEL: @test_sub_255_Y_eq_255_vec( 137; CHECK-NEXT: [[Z:%.*]] = icmp eq <2 x i8> [[Y:%.*]], zeroinitializer 138; CHECK-NEXT: ret <2 x i1> [[Z]] 139; 140 %s = sub <2 x i8> <i8 255, i8 255>, %y 141 %z = icmp eq <2 x i8> %s, <i8 255, i8 255> 142 ret <2 x i1> %z 143} 144 145define <2 x i1> @icmp_eq_sub_undef(<2 x i32> %a) { 146; CHECK-LABEL: @icmp_eq_sub_undef( 147; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 5, i32 undef> 148; CHECK-NEXT: ret <2 x i1> [[CMP]] 149; 150 %sub = sub <2 x i32> <i32 15, i32 undef>, %a 151 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 10> 152 ret <2 x i1> %cmp 153} 154 155define <2 x i1> @icmp_eq_sub_non_splat(<2 x i32> %a) { 156; CHECK-LABEL: @icmp_eq_sub_non_splat( 157; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 5, i32 6> 158; CHECK-NEXT: ret <2 x i1> [[CMP]] 159; 160 %sub = sub <2 x i32> <i32 15, i32 16>, %a 161 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 10> 162 ret <2 x i1> %cmp 163} 164 165define <2 x i1> @icmp_eq_sub_undef2(<2 x i32> %a) { 166; CHECK-LABEL: @icmp_eq_sub_undef2( 167; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[A:%.*]] 168; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[SUB]], <i32 10, i32 undef> 169; CHECK-NEXT: ret <2 x i1> [[CMP]] 170; 171 %sub = sub <2 x i32> <i32 15, i32 15>, %a 172 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 undef> 173 ret <2 x i1> %cmp 174} 175 176define <2 x i1> @icmp_eq_sub_non_splat2(<2 x i32> %a) { 177; CHECK-LABEL: @icmp_eq_sub_non_splat2( 178; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[A:%.*]] 179; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[SUB]], <i32 10, i32 11> 180; CHECK-NEXT: ret <2 x i1> [[CMP]] 181; 182 %sub = sub <2 x i32> <i32 15, i32 15>, %a 183 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 11> 184 ret <2 x i1> %cmp 185} 186 187define i1 @neg_sgt_42(i32 %x) { 188; CHECK-LABEL: @neg_sgt_42( 189; CHECK-NEXT: [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1 190; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[NOTSUB]], -43 191; CHECK-NEXT: ret i1 [[R]] 192; 193 %negx = sub i32 0, %x 194 %r = icmp sgt i32 %negx, 42 195 ret i1 %r 196} 197 198define i1 @neg_eq_43(i32 %x) { 199; CHECK-LABEL: @neg_eq_43( 200; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]] 201; CHECK-NEXT: call void @use(i32 [[NEGX]]) 202; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -43 203; CHECK-NEXT: ret i1 [[R]] 204; 205 %negx = sub i32 0, %x 206 call void @use(i32 %negx) 207 %r = icmp eq i32 %negx, 43 208 ret i1 %r 209} 210 211define i1 @neg_ne_44(i32 %x) { 212; CHECK-LABEL: @neg_ne_44( 213; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]] 214; CHECK-NEXT: call void @use(i32 [[NEGX]]) 215; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -44 216; CHECK-NEXT: ret i1 [[R]] 217; 218 %negx = sub i32 0, %x 219 call void @use(i32 %negx) 220 %r = icmp ne i32 %negx, 44 221 ret i1 %r 222} 223 224define i1 @neg_nsw_eq_45(i32 %x) { 225; CHECK-LABEL: @neg_nsw_eq_45( 226; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]] 227; CHECK-NEXT: call void @use(i32 [[NEGX]]) 228; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -45 229; CHECK-NEXT: ret i1 [[R]] 230; 231 %negx = sub nsw i32 0, %x 232 call void @use(i32 %negx) 233 %r = icmp eq i32 %negx, 45 234 ret i1 %r 235} 236 237define i1 @neg_nsw_ne_46(i32 %x) { 238; CHECK-LABEL: @neg_nsw_ne_46( 239; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]] 240; CHECK-NEXT: call void @use(i32 [[NEGX]]) 241; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -46 242; CHECK-NEXT: ret i1 [[R]] 243; 244 %negx = sub nsw i32 0, %x 245 call void @use(i32 %negx) 246 %r = icmp ne i32 %negx, 46 247 ret i1 %r 248} 249 250define i1 @subC_eq(i32 %x) { 251; CHECK-LABEL: @subC_eq( 252; CHECK-NEXT: [[SUBX:%.*]] = sub i32 -2147483648, [[X:%.*]] 253; CHECK-NEXT: call void @use(i32 [[SUBX]]) 254; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483605 255; CHECK-NEXT: ret i1 [[R]] 256; 257 %subx = sub i32 -2147483648, %x 258 call void @use(i32 %subx) 259 %r = icmp eq i32 %subx, 43 260 ret i1 %r 261} 262 263define <2 x i1> @subC_ne(<2 x i8> %x) { 264; CHECK-LABEL: @subC_ne( 265; CHECK-NEXT: [[SUBX:%.*]] = sub <2 x i8> <i8 -6, i8 -128>, [[X:%.*]] 266; CHECK-NEXT: call void @use_vec(<2 x i8> [[SUBX]]) 267; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[X]], <i8 38, i8 -84> 268; CHECK-NEXT: ret <2 x i1> [[R]] 269; 270 %subx = sub <2 x i8> <i8 -6, i8 -128>, %x 271 call void @use_vec(<2 x i8> %subx) 272 %r = icmp ne <2 x i8> %subx, <i8 -44, i8 -44> 273 ret <2 x i1> %r 274} 275 276define i1 @subC_nsw_eq(i32 %x) { 277; CHECK-LABEL: @subC_nsw_eq( 278; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -100, [[X:%.*]] 279; CHECK-NEXT: call void @use(i32 [[SUBX]]) 280; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483548 281; CHECK-NEXT: ret i1 [[R]] 282; 283 %subx = sub nsw i32 -100, %x 284 call void @use(i32 %subx) 285 %r = icmp eq i32 %subx, -2147483648 286 ret i1 %r 287} 288 289define i1 @subC_nsw_ne(i32 %x) { 290; CHECK-LABEL: @subC_nsw_ne( 291; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -2147483647, [[X:%.*]] 292; CHECK-NEXT: call void @use(i32 [[SUBX]]) 293; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], 2147483603 294; CHECK-NEXT: ret i1 [[R]] 295; 296 %subx = sub nsw i32 -2147483647, %x 297 call void @use(i32 %subx) 298 %r = icmp ne i32 %subx, 46 299 ret i1 %r 300} 301 302define i1 @neg_slt_42(i128 %x) { 303; CHECK-LABEL: @neg_slt_42( 304; CHECK-NEXT: [[NOTSUB:%.*]] = add i128 [[X:%.*]], -1 305; CHECK-NEXT: [[R:%.*]] = icmp sgt i128 [[NOTSUB]], -43 306; CHECK-NEXT: ret i1 [[R]] 307; 308 %negx = sub i128 0, %x 309 %r = icmp slt i128 %negx, 42 310 ret i1 %r 311} 312 313define <2 x i1> @neg_ugt_42_splat(<2 x i7> %x) { 314; CHECK-LABEL: @neg_ugt_42_splat( 315; CHECK-NEXT: [[NOTSUB:%.*]] = add <2 x i7> [[X:%.*]], splat (i7 -1) 316; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i7> [[NOTSUB]], splat (i7 -43) 317; CHECK-NEXT: ret <2 x i1> [[R]] 318; 319 %negx = sub <2 x i7> zeroinitializer, %x 320 %r = icmp ugt <2 x i7> %negx, <i7 42, i7 42> 321 ret <2 x i1> %r 322} 323 324define i1 @neg_sgt_42_use(i32 %x) { 325; CHECK-LABEL: @neg_sgt_42_use( 326; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]] 327; CHECK-NEXT: call void @use(i32 [[NEGX]]) 328; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[NEGX]], 42 329; CHECK-NEXT: ret i1 [[R]] 330; 331 %negx = sub i32 0, %x 332 call void @use(i32 %negx) 333 %r = icmp sgt i32 %negx, 42 334 ret i1 %r 335} 336 337; Test common/edge cases with signed pred. 338 339define i1 @neg_slt_n1(i8 %x) { 340; CHECK-LABEL: @neg_slt_n1( 341; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1 342; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NOTSUB]], 0 343; CHECK-NEXT: ret i1 [[R]] 344; 345 %negx = sub i8 0, %x 346 %r = icmp slt i8 %negx, -1 347 ret i1 %r 348} 349 350define i1 @neg_slt_0(i8 %x) { 351; CHECK-LABEL: @neg_slt_0( 352; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1 353; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp sgt i8 [[NOTSUB]], -1 354; CHECK-NEXT: ret i1 [[ISNEGNEG]] 355; 356 %negx = sub i8 0, %x 357 %isnegneg = icmp slt i8 %negx, 0 358 ret i1 %isnegneg 359} 360 361define i1 @neg_slt_1(i8 %x) { 362; CHECK-LABEL: @neg_slt_1( 363; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X:%.*]], -127 364; CHECK-NEXT: ret i1 [[R]] 365; 366 %negx = sub i8 0, %x 367 %r = icmp slt i8 %negx, 1 368 ret i1 %r 369} 370 371define i1 @neg_sgt_n1(i8 %x) { 372; CHECK-LABEL: @neg_sgt_n1( 373; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1 374; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], 0 375; CHECK-NEXT: ret i1 [[R]] 376; 377 %negx = sub i8 0, %x 378 %r = icmp sgt i8 %negx, -1 379 ret i1 %r 380} 381 382define i1 @neg_sgt_0(i8 %x) { 383; CHECK-LABEL: @neg_sgt_0( 384; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X:%.*]], -128 385; CHECK-NEXT: ret i1 [[R]] 386; 387 %negx = sub i8 0, %x 388 %r = icmp sgt i8 %negx, 0 389 ret i1 %r 390} 391 392define i1 @neg_sgt_1(i8 %x) { 393; CHECK-LABEL: @neg_sgt_1( 394; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1 395; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], -2 396; CHECK-NEXT: ret i1 [[R]] 397; 398 %negx = sub i8 0, %x 399 %r = icmp sgt i8 %negx, 1 400 ret i1 %r 401} 402 403; Test common/edge cases with signed pred and nsw. 404 405define i1 @neg_nsw_slt_n1(i8 %x) { 406; CHECK-LABEL: @neg_nsw_slt_n1( 407; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X:%.*]], 1 408; CHECK-NEXT: ret i1 [[R]] 409; 410 %negx = sub nsw i8 0, %x 411 %r = icmp slt i8 %negx, -1 412 ret i1 %r 413} 414 415define i1 @neg_nsw_slt_0(i8 %x) { 416; CHECK-LABEL: @neg_nsw_slt_0( 417; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp sgt i8 [[X:%.*]], 0 418; CHECK-NEXT: ret i1 [[ISNEGNEG]] 419; 420 %negx = sub nsw i8 0, %x 421 %isnegneg = icmp slt i8 %negx, 0 422 ret i1 %isnegneg 423} 424 425define i1 @neg_nsw_slt_1(i8 %x) { 426; CHECK-LABEL: @neg_nsw_slt_1( 427; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X:%.*]], -1 428; CHECK-NEXT: ret i1 [[R]] 429; 430 %negx = sub nsw i8 0, %x 431 %r = icmp slt i8 %negx, 1 432 ret i1 %r 433} 434 435define i1 @neg_nsw_sgt_n1(i8 %x) { 436; CHECK-LABEL: @neg_nsw_sgt_n1( 437; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], 1 438; CHECK-NEXT: ret i1 [[R]] 439; 440 %negx = sub nsw i8 0, %x 441 %r = icmp sgt i8 %negx, -1 442 ret i1 %r 443} 444 445define i1 @neg_nsw_sgt_0(i8 %x) { 446; CHECK-LABEL: @neg_nsw_sgt_0( 447; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], 0 448; CHECK-NEXT: ret i1 [[R]] 449; 450 %negx = sub nsw i8 0, %x 451 %r = icmp sgt i8 %negx, 0 452 ret i1 %r 453} 454 455define i1 @neg_nsw_sgt_1(i8 %x) { 456; CHECK-LABEL: @neg_nsw_sgt_1( 457; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], -1 458; CHECK-NEXT: ret i1 [[R]] 459; 460 %negx = sub nsw i8 0, %x 461 %r = icmp sgt i8 %negx, 1 462 ret i1 %r 463} 464 465define i1 @sub_eq_zero_use(i32 %x, i32 %y) { 466; CHECK-LABEL: @sub_eq_zero_use( 467; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]] 468; CHECK-NEXT: call void @use(i32 [[SUB]]) 469; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], [[Y]] 470; CHECK-NEXT: ret i1 [[R]] 471; 472 %sub = sub i32 %x, %y 473 call void @use(i32 %sub) 474 %r = icmp eq i32 %sub, 0 475 ret i1 %r 476} 477 478define <2 x i1> @sub_ne_zero_use(<2 x i8> %x, <2 x i8> %y) { 479; CHECK-LABEL: @sub_ne_zero_use( 480; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]] 481; CHECK-NEXT: call void @use_vec(<2 x i8> [[SUB]]) 482; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[X]], [[Y]] 483; CHECK-NEXT: ret <2 x i1> [[R]] 484; 485 %sub = sub <2 x i8> %x, %y 486 call void @use_vec(<2 x i8> %sub) 487 %r = icmp eq <2 x i8> %sub, zeroinitializer 488 ret <2 x i1> %r 489} 490 491define i32 @sub_eq_zero_select(i32 %a, i32 %b, ptr %p) { 492; CHECK-LABEL: @sub_eq_zero_select( 493; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 494; CHECK-NEXT: store i32 [[SUB]], ptr [[P:%.*]], align 4 495; CHECK-NEXT: ret i32 [[B]] 496; 497 %sub = sub i32 %a, %b 498 store i32 %sub, ptr %p 499 %cmp = icmp eq i32 %sub, 0 500 %sel = select i1 %cmp, i32 %a, i32 %b 501 ret i32 %sel 502} 503 504; Replacing the "SUB == 0" regresses codegen, and it may be hard to recover from that. 505 506declare i32 @llvm.umin.i32(i32, i32) 507 508define void @PR54558_reduced(i32 %arg) { 509; CHECK-LABEL: @PR54558_reduced( 510; CHECK-NEXT: bb_entry: 511; CHECK-NEXT: br label [[BB_LOOP:%.*]] 512; CHECK: bb_loop: 513; CHECK-NEXT: [[PHI_OUTER:%.*]] = phi i32 [ [[SUB:%.*]], [[BB_LOOP]] ], [ [[ARG:%.*]], [[BB_ENTRY:%.*]] ] 514; CHECK-NEXT: [[MIN:%.*]] = tail call i32 @llvm.umin.i32(i32 [[PHI_OUTER]], i32 43) 515; CHECK-NEXT: call void @use(i32 [[MIN]]) 516; CHECK-NEXT: [[SUB]] = sub i32 [[PHI_OUTER]], [[MIN]] 517; CHECK-NEXT: [[COND_OUTER:%.*]] = icmp eq i32 [[SUB]], 0 518; CHECK-NEXT: br i1 [[COND_OUTER]], label [[BB_EXIT:%.*]], label [[BB_LOOP]] 519; CHECK: bb_exit: 520; CHECK-NEXT: ret void 521; 522bb_entry: 523 br label %bb_loop 524 525bb_loop: 526 %phi_outer = phi i32 [ %sub, %bb_loop ], [ %arg, %bb_entry ] 527 %min = tail call i32 @llvm.umin.i32(i32 %phi_outer, i32 43) 528 call void @use(i32 %min) 529 %sub = sub i32 %phi_outer, %min 530 %cond_outer = icmp eq i32 %sub, 0 531 br i1 %cond_outer, label %bb_exit, label %bb_loop 532 533bb_exit: 534 ret void 535} 536 537; TODO: It might be ok to replace the "SUB == 0" in this example if codegen can invert it. 538 539define void @PR54558_reduced_more(i32 %x, i32 %y) { 540; CHECK-LABEL: @PR54558_reduced_more( 541; CHECK-NEXT: bb_entry: 542; CHECK-NEXT: br label [[BB_LOOP:%.*]] 543; CHECK: bb_loop: 544; CHECK-NEXT: [[PHI_OUTER:%.*]] = phi i32 [ [[SUB:%.*]], [[BB_LOOP]] ], [ [[X:%.*]], [[BB_ENTRY:%.*]] ] 545; CHECK-NEXT: [[SUB]] = sub i32 [[PHI_OUTER]], [[Y:%.*]] 546; CHECK-NEXT: [[COND_OUTER:%.*]] = icmp eq i32 [[SUB]], 0 547; CHECK-NEXT: br i1 [[COND_OUTER]], label [[BB_EXIT:%.*]], label [[BB_LOOP]] 548; CHECK: bb_exit: 549; CHECK-NEXT: ret void 550; 551bb_entry: 552 br label %bb_loop 553 554bb_loop: 555 %phi_outer = phi i32 [ %sub, %bb_loop ], [ %x, %bb_entry ] 556 %sub = sub i32 %phi_outer, %y 557 %cond_outer = icmp eq i32 %sub, 0 558 br i1 %cond_outer, label %bb_exit, label %bb_loop 559 560bb_exit: 561 ret void 562} 563 564; https://alive2.llvm.org/ce/z/D2Aph4 565define i1 @PR60818_ne(i32 %a) { 566; CHECK-LABEL: @PR60818_ne( 567; CHECK-NEXT: entry: 568; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647 569; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0]], 0 570; CHECK-NEXT: ret i1 [[CMP]] 571; 572entry: 573 %sub = sub i32 0, %a 574 %cmp = icmp ne i32 %sub, %a 575 ret i1 %cmp 576} 577 578define i1 @PR60818_eq(i32 %a) { 579; CHECK-LABEL: @PR60818_eq( 580; CHECK-NEXT: entry: 581; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647 582; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 583; CHECK-NEXT: ret i1 [[CMP]] 584; 585entry: 586 %sub = sub i32 0, %a 587 %cmp = icmp eq i32 %sub, %a 588 ret i1 %cmp 589} 590 591define i1 @PR60818_eq_commuted(i32 %x) { 592; CHECK-LABEL: @PR60818_eq_commuted( 593; CHECK-NEXT: entry: 594; CHECK-NEXT: [[A:%.*]] = mul i32 [[X:%.*]], 43 595; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A]], 2147483647 596; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 597; CHECK-NEXT: ret i1 [[CMP]] 598; 599entry: 600 %a = mul i32 %x, 43 ; thwart complexity-based canonicalization 601 %sub = sub i32 0, %a 602 %cmp = icmp eq i32 %a, %sub ; negation on RHS 603 ret i1 %cmp 604} 605 606define <2 x i1> @PR60818_ne_vector(<2 x i32> %a) { 607; CHECK-LABEL: @PR60818_ne_vector( 608; CHECK-NEXT: entry: 609; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647) 610; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP0]], zeroinitializer 611; CHECK-NEXT: ret <2 x i1> [[CMP]] 612; 613entry: 614 %sub = sub <2 x i32> zeroinitializer, %a 615 %cmp = icmp ne <2 x i32> %a, %sub 616 ret <2 x i1> %cmp 617} 618 619; Negative as multi-use 620define i1 @PR60818_eq_multi_use(i32 %a) { 621; CHECK-LABEL: @PR60818_eq_multi_use( 622; CHECK-NEXT: entry: 623; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] 624; CHECK-NEXT: call void @use(i32 [[SUB]]) 625; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], [[SUB]] 626; CHECK-NEXT: ret i1 [[CMP]] 627; 628entry: 629 %sub = sub i32 0, %a 630 call void @use(i32 %sub) ; add new user 631 %cmp = icmp eq i32 %sub, %a 632 ret i1 %cmp 633} 634 635; Negative as non-equality predicate 636define i1 @PR60818_sgt(i32 %a) { 637; CHECK-LABEL: @PR60818_sgt( 638; CHECK-NEXT: entry: 639; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] 640; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[SUB]] 641; CHECK-NEXT: ret i1 [[CMP]] 642; 643entry: 644 %sub = sub i32 0, %a 645 %cmp = icmp sgt i32 %sub, %a 646 ret i1 %cmp 647} 648