1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @llvm.assume(i1) 5declare void @use(i8) 6declare void @usev2xi8(<2 x i8>) 7 8 9define i1 @squared_nsw_eq0(i5 %x) { 10; CHECK-LABEL: @squared_nsw_eq0( 11; CHECK-NEXT: [[R:%.*]] = icmp eq i5 [[X:%.*]], 0 12; CHECK-NEXT: ret i1 [[R]] 13; 14 %m = mul nsw i5 %x, %x 15 %r = icmp eq i5 %m, 0 16 ret i1 %r 17} 18 19define <2 x i1> @squared_nuw_eq0(<2 x i8> %x) { 20; CHECK-LABEL: @squared_nuw_eq0( 21; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer 22; CHECK-NEXT: ret <2 x i1> [[R]] 23; 24 %m = mul nuw <2 x i8> %x, %x 25 %r = icmp eq <2 x i8> %m, zeroinitializer 26 ret <2 x i1> %r 27} 28 29; extra use is ok 30 31define i1 @squared_nsw_nuw_ne0(i8 %x) { 32; CHECK-LABEL: @squared_nsw_nuw_ne0( 33; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]] 34; CHECK-NEXT: call void @use(i8 [[M]]) 35; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], 0 36; CHECK-NEXT: ret i1 [[R]] 37; 38 %m = mul nsw nuw i8 %x, %x 39 call void @use(i8 %m) 40 %r = icmp ne i8 %m, 0 41 ret i1 %r 42} 43 44; negative test - must have no-overflow 45 46define i1 @squared_eq0(i8 %x) { 47; CHECK-LABEL: @squared_eq0( 48; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[X]] 49; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0 50; CHECK-NEXT: ret i1 [[R]] 51; 52 %m = mul i8 %x, %x 53 %r = icmp eq i8 %m, 0 54 ret i1 %r 55} 56 57; negative test - not squared 58; TODO: This could be or-of-icmps. 59 60define i1 @mul_nsw_eq0(i5 %x, i5 %y) { 61; CHECK-LABEL: @mul_nsw_eq0( 62; CHECK-NEXT: [[M:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]] 63; CHECK-NEXT: [[R:%.*]] = icmp eq i5 [[M]], 0 64; CHECK-NEXT: ret i1 [[R]] 65; 66 %m = mul nsw i5 %x, %y 67 %r = icmp eq i5 %m, 0 68 ret i1 %r 69} 70 71; negative test - non-zero cmp 72 73define i1 @squared_nsw_eq1(i5 %x) { 74; CHECK-LABEL: @squared_nsw_eq1( 75; CHECK-NEXT: [[M:%.*]] = mul nsw i5 [[X:%.*]], [[X]] 76; CHECK-NEXT: [[R:%.*]] = icmp eq i5 [[M]], 1 77; CHECK-NEXT: ret i1 [[R]] 78; 79 %m = mul nsw i5 %x, %x 80 %r = icmp eq i5 %m, 1 81 ret i1 %r 82} 83 84define i1 @squared_nsw_sgt0(i5 %x) { 85; CHECK-LABEL: @squared_nsw_sgt0( 86; CHECK-NEXT: [[R:%.*]] = icmp ne i5 [[X:%.*]], 0 87; CHECK-NEXT: ret i1 [[R]] 88; 89 %m = mul nsw i5 %x, %x 90 %r = icmp sgt i5 %m, 0 91 ret i1 %r 92} 93 94; Tests for slt/ult 95 96define i1 @slt_positive_multip_rem_zero(i8 %x) { 97; CHECK-LABEL: @slt_positive_multip_rem_zero( 98; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], 3 99; CHECK-NEXT: ret i1 [[B]] 100; 101 %a = mul nsw i8 %x, 7 102 %b = icmp slt i8 %a, 21 103 ret i1 %b 104} 105 106define i1 @slt_negative_multip_rem_zero(i8 %x) { 107; CHECK-LABEL: @slt_negative_multip_rem_zero( 108; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], -3 109; CHECK-NEXT: ret i1 [[B]] 110; 111 %a = mul nsw i8 %x, -7 112 %b = icmp slt i8 %a, 21 113 ret i1 %b 114} 115 116define i1 @slt_positive_multip_rem_nz(i8 %x) { 117; CHECK-LABEL: @slt_positive_multip_rem_nz( 118; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], 5 119; CHECK-NEXT: ret i1 [[B]] 120; 121 %a = mul nsw i8 %x, 5 122 %b = icmp slt i8 %a, 21 123 ret i1 %b 124} 125 126define i1 @ult_rem_zero(i8 %x) { 127; CHECK-LABEL: @ult_rem_zero( 128; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 3 129; CHECK-NEXT: ret i1 [[B]] 130; 131 %a = mul nuw i8 %x, 7 132 %b = icmp ult i8 %a, 21 133 ret i1 %b 134} 135 136; Same as above, but with nsw flag too. 137; This used to not optimize due to nsw being prioritized too much. 138define i1 @ult_rem_zero_nsw(i8 %x) { 139; CHECK-LABEL: @ult_rem_zero_nsw( 140; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 3 141; CHECK-NEXT: ret i1 [[B]] 142; 143 %a = mul nuw nsw i8 %x, 7 144 %b = icmp ult i8 %a, 21 145 ret i1 %b 146} 147 148define i1 @ult_rem_nz(i8 %x) { 149; CHECK-LABEL: @ult_rem_nz( 150; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 5 151; CHECK-NEXT: ret i1 [[B]] 152; 153 %a = mul nuw i8 %x, 5 154 %b = icmp ult i8 %a, 21 155 ret i1 %b 156} 157 158; Same as above, but with nsw flag too. 159; This used to not optimize due to nsw being prioritized too much. 160define i1 @ult_rem_nz_nsw(i8 %x) { 161; CHECK-LABEL: @ult_rem_nz_nsw( 162; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 5 163; CHECK-NEXT: ret i1 [[B]] 164; 165 %a = mul nuw nsw i8 %x, 5 166 %b = icmp ult i8 %a, 21 167 ret i1 %b 168} 169 170; Tests for sgt/ugt 171 172define i1 @sgt_positive_multip_rem_zero(i8 %x) { 173; CHECK-LABEL: @sgt_positive_multip_rem_zero( 174; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], 3 175; CHECK-NEXT: ret i1 [[B]] 176; 177 %a = mul nsw i8 %x, 7 178 %b = icmp sgt i8 %a, 21 179 ret i1 %b 180} 181 182define i1 @sgt_negative_multip_rem_zero(i8 %x) { 183; CHECK-LABEL: @sgt_negative_multip_rem_zero( 184; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], -3 185; CHECK-NEXT: ret i1 [[B]] 186; 187 %a = mul nsw i8 %x, -7 188 %b = icmp sgt i8 %a, 21 189 ret i1 %b 190} 191 192define i1 @sgt_positive_multip_rem_nz(i8 %x) { 193; CHECK-LABEL: @sgt_positive_multip_rem_nz( 194; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], 4 195; CHECK-NEXT: ret i1 [[B]] 196; 197 %a = mul nsw i8 %x, 5 198 %b = icmp sgt i8 %a, 21 199 ret i1 %b 200} 201 202define i1 @ugt_rem_zero(i8 %x) { 203; CHECK-LABEL: @ugt_rem_zero( 204; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3 205; CHECK-NEXT: ret i1 [[B]] 206; 207 %a = mul nuw i8 %x, 7 208 %b = icmp ugt i8 %a, 21 209 ret i1 %b 210} 211 212; Same as above, but with nsw flag too. 213; This used to not optimize due to nsw being prioritized too much. 214define i1 @ugt_rem_zero_nsw(i8 %x) { 215; CHECK-LABEL: @ugt_rem_zero_nsw( 216; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3 217; CHECK-NEXT: ret i1 [[B]] 218; 219 %a = mul nuw nsw i8 %x, 7 220 %b = icmp ugt i8 %a, 21 221 ret i1 %b 222} 223 224define i1 @ugt_rem_nz(i8 %x) { 225; CHECK-LABEL: @ugt_rem_nz( 226; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4 227; CHECK-NEXT: ret i1 [[B]] 228; 229 %a = mul nuw i8 %x, 5 230 %b = icmp ugt i8 %a, 21 231 ret i1 %b 232} 233 234; Same as above, but with nsw flag too. 235; This used to not optimize due to nsw being prioritized too much. 236define i1 @ugt_rem_nz_nsw(i8 %x) { 237; CHECK-LABEL: @ugt_rem_nz_nsw( 238; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4 239; CHECK-NEXT: ret i1 [[B]] 240; 241 %a = mul nuw nsw i8 %x, 5 242 %b = icmp ugt i8 %a, 21 243 ret i1 %b 244} 245 246; Tests for eq/ne 247 248define i1 @eq_nsw_rem_zero(i8 %x) { 249; CHECK-LABEL: @eq_nsw_rem_zero( 250; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X:%.*]], -4 251; CHECK-NEXT: ret i1 [[B]] 252; 253 %a = mul nsw i8 %x, -5 254 %b = icmp eq i8 %a, 20 255 ret i1 %b 256} 257 258define <2 x i1> @ne_nsw_rem_zero(<2 x i8> %x) { 259; CHECK-LABEL: @ne_nsw_rem_zero( 260; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[X:%.*]], splat (i8 -6) 261; CHECK-NEXT: ret <2 x i1> [[B]] 262; 263 %a = mul nsw <2 x i8> %x, <i8 5, i8 5> 264 %b = icmp ne <2 x i8> %a, <i8 -30, i8 -30> 265 ret <2 x i1> %b 266} 267 268; TODO: Missed fold with undef. 269 270define <2 x i1> @ne_nsw_rem_zero_undef1(<2 x i8> %x) { 271; CHECK-LABEL: @ne_nsw_rem_zero_undef1( 272; CHECK-NEXT: [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 5, i8 undef> 273; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[A]], splat (i8 -30) 274; CHECK-NEXT: ret <2 x i1> [[B]] 275; 276 %a = mul nsw <2 x i8> %x, <i8 5, i8 undef> 277 %b = icmp ne <2 x i8> %a, <i8 -30, i8 -30> 278 ret <2 x i1> %b 279} 280 281; TODO: Missed fold with undef. 282 283define <2 x i1> @ne_nsw_rem_zero_undef2(<2 x i8> %x) { 284; CHECK-LABEL: @ne_nsw_rem_zero_undef2( 285; CHECK-NEXT: [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], splat (i8 5) 286; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[A]], <i8 -30, i8 undef> 287; CHECK-NEXT: ret <2 x i1> [[B]] 288; 289 %a = mul nsw <2 x i8> %x, <i8 5, i8 5> 290 %b = icmp ne <2 x i8> %a, <i8 -30, i8 undef> 291 ret <2 x i1> %b 292} 293 294define i1 @eq_nsw_rem_zero_uses(i8 %x) { 295; CHECK-LABEL: @eq_nsw_rem_zero_uses( 296; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], -5 297; CHECK-NEXT: call void @use(i8 [[A]]) 298; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X]], -4 299; CHECK-NEXT: ret i1 [[B]] 300; 301 %a = mul nsw i8 %x, -5 302 call void @use(i8 %a) 303 %b = icmp eq i8 %a, 20 304 ret i1 %b 305} 306 307; Impossible multiple should be handled by instsimplify. 308 309define i1 @eq_nsw_rem_nz(i8 %x) { 310; CHECK-LABEL: @eq_nsw_rem_nz( 311; CHECK-NEXT: ret i1 false 312; 313 %a = mul nsw i8 %x, 5 314 %b = icmp eq i8 %a, 245 315 ret i1 %b 316} 317 318; Impossible multiple should be handled by instsimplify. 319 320define i1 @ne_nsw_rem_nz(i8 %x) { 321; CHECK-LABEL: @ne_nsw_rem_nz( 322; CHECK-NEXT: ret i1 true 323; 324 %a = mul nsw i8 %x, 5 325 %b = icmp ne i8 %a, 130 326 ret i1 %b 327} 328 329define <2 x i1> @eq_nuw_rem_zero(<2 x i8> %x) { 330; CHECK-LABEL: @eq_nuw_rem_zero( 331; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 4) 332; CHECK-NEXT: ret <2 x i1> [[B]] 333; 334 %a = mul nuw <2 x i8> %x, <i8 5, i8 5> 335 %b = icmp eq <2 x i8> %a, <i8 20, i8 20> 336 ret <2 x i1> %b 337} 338 339; TODO: Missed fold with undef. 340 341define <2 x i1> @eq_nuw_rem_zero_undef1(<2 x i8> %x) { 342; CHECK-LABEL: @eq_nuw_rem_zero_undef1( 343; CHECK-NEXT: [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], <i8 undef, i8 5> 344; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[A]], splat (i8 20) 345; CHECK-NEXT: ret <2 x i1> [[B]] 346; 347 %a = mul nuw <2 x i8> %x, <i8 undef, i8 5> 348 %b = icmp eq <2 x i8> %a, <i8 20, i8 20> 349 ret <2 x i1> %b 350} 351 352; TODO: Missed fold with undef. 353 354define <2 x i1> @eq_nuw_rem_zero_undef2(<2 x i8> %x) { 355; CHECK-LABEL: @eq_nuw_rem_zero_undef2( 356; CHECK-NEXT: [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], splat (i8 5) 357; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[A]], <i8 undef, i8 20> 358; CHECK-NEXT: ret <2 x i1> [[B]] 359; 360 %a = mul nuw <2 x i8> %x, <i8 5, i8 5> 361 %b = icmp eq <2 x i8> %a, <i8 undef, i8 20> 362 ret <2 x i1> %b 363} 364 365define i1 @ne_nuw_rem_zero(i8 %x) { 366; CHECK-LABEL: @ne_nuw_rem_zero( 367; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X:%.*]], 26 368; CHECK-NEXT: ret i1 [[B]] 369; 370 %a = mul nuw i8 %x, 5 371 %b = icmp ne i8 %a, 130 372 ret i1 %b 373} 374 375define i1 @ne_nuw_rem_zero_uses(i8 %x) { 376; CHECK-LABEL: @ne_nuw_rem_zero_uses( 377; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 5 378; CHECK-NEXT: call void @use(i8 [[A]]) 379; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X]], 26 380; CHECK-NEXT: ret i1 [[B]] 381; 382 %a = mul nuw i8 %x, 5 383 call void @use(i8 %a) 384 %b = icmp ne i8 %a, 130 385 ret i1 %b 386} 387 388; Impossible multiple should be handled by instsimplify. 389 390define i1 @eq_nuw_rem_nz(i8 %x) { 391; CHECK-LABEL: @eq_nuw_rem_nz( 392; CHECK-NEXT: ret i1 false 393; 394 %a = mul nuw i8 %x, -5 395 %b = icmp eq i8 %a, 20 396 ret i1 %b 397} 398 399; Impossible multiple should be handled by instsimplify. 400 401define i1 @ne_nuw_rem_nz(i8 %x) { 402; CHECK-LABEL: @ne_nuw_rem_nz( 403; CHECK-NEXT: ret i1 true 404; 405 %a = mul nuw i8 %x, 5 406 %b = icmp ne i8 %a, -30 407 ret i1 %b 408} 409 410; Negative tests for the icmp mul folds 411 412define i1 @sgt_positive_multip_rem_zero_nonsw(i8 %x) { 413; CHECK-LABEL: @sgt_positive_multip_rem_zero_nonsw( 414; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 7 415; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[A]], 21 416; CHECK-NEXT: ret i1 [[B]] 417; 418 %a = mul i8 %x, 7 419 %b = icmp sgt i8 %a, 21 420 ret i1 %b 421} 422 423define i1 @ult_multip_rem_zero_nonsw(i8 %x) { 424; CHECK-LABEL: @ult_multip_rem_zero_nonsw( 425; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 7 426; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[A]], 21 427; CHECK-NEXT: ret i1 [[B]] 428; 429 %a = mul i8 %x, 7 430 %b = icmp ult i8 %a, 21 431 ret i1 %b 432} 433 434define i1 @ugt_rem_zero_nonuw(i8 %x) { 435; CHECK-LABEL: @ugt_rem_zero_nonuw( 436; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 7 437; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], 21 438; CHECK-NEXT: ret i1 [[B]] 439; 440 %a = mul i8 %x, 7 441 %b = icmp ugt i8 %a, 21 442 ret i1 %b 443} 444 445define i1 @sgt_minnum(i8 %x) { 446; CHECK-LABEL: @sgt_minnum( 447; CHECK-NEXT: ret i1 true 448; 449 %a = mul nsw i8 %x, 7 450 %b = icmp sgt i8 %a, -128 451 ret i1 %b 452} 453 454define i1 @ule_bignum(i8 %x) { 455; CHECK-LABEL: @ule_bignum( 456; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X:%.*]], 0 457; CHECK-NEXT: ret i1 [[B]] 458; 459 %a = mul i8 %x, 2147483647 460 %b = icmp ule i8 %a, 0 461 ret i1 %b 462} 463 464define i1 @sgt_mulzero(i8 %x) { 465; CHECK-LABEL: @sgt_mulzero( 466; CHECK-NEXT: ret i1 false 467; 468 %a = mul nsw i8 %x, 0 469 %b = icmp sgt i8 %a, 21 470 ret i1 %b 471} 472 473define i1 @eq_rem_zero_nonuw(i8 %x) { 474; CHECK-LABEL: @eq_rem_zero_nonuw( 475; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X:%.*]], 4 476; CHECK-NEXT: ret i1 [[B]] 477; 478 %a = mul i8 %x, 5 479 %b = icmp eq i8 %a, 20 480 ret i1 %b 481} 482 483define i1 @ne_rem_zero_nonuw(i8 %x) { 484; CHECK-LABEL: @ne_rem_zero_nonuw( 485; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X:%.*]], 6 486; CHECK-NEXT: ret i1 [[B]] 487; 488 %a = mul i8 %x, 5 489 %b = icmp ne i8 %a, 30 490 ret i1 %b 491} 492 493define i1 @mul_constant_eq(i32 %x, i32 %y) { 494; CHECK-LABEL: @mul_constant_eq( 495; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] 496; CHECK-NEXT: ret i1 [[C]] 497; 498 %A = mul i32 %x, 5 499 %B = mul i32 %y, 5 500 %C = icmp eq i32 %A, %B 501 ret i1 %C 502} 503 504define <2 x i1> @mul_constant_ne_splat(<2 x i32> %x, <2 x i32> %y) { 505; CHECK-LABEL: @mul_constant_ne_splat( 506; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] 507; CHECK-NEXT: ret <2 x i1> [[C]] 508; 509 %A = mul <2 x i32> %x, <i32 5, i32 5> 510 %B = mul <2 x i32> %y, <i32 5, i32 5> 511 %C = icmp ne <2 x i32> %A, %B 512 ret <2 x i1> %C 513} 514 515define i1 @mul_constant_ne_extra_use1(i8 %x, i8 %y) { 516; CHECK-LABEL: @mul_constant_ne_extra_use1( 517; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 5 518; CHECK-NEXT: call void @use(i8 [[A]]) 519; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]] 520; CHECK-NEXT: ret i1 [[C]] 521; 522 %A = mul i8 %x, 5 523 call void @use(i8 %A) 524 %B = mul i8 %y, 5 525 %C = icmp ne i8 %A, %B 526 ret i1 %C 527} 528 529define i1 @mul_constant_eq_extra_use2(i8 %x, i8 %y) { 530; CHECK-LABEL: @mul_constant_eq_extra_use2( 531; CHECK-NEXT: [[B:%.*]] = mul i8 [[Y:%.*]], 5 532; CHECK-NEXT: call void @use(i8 [[B]]) 533; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]] 534; CHECK-NEXT: ret i1 [[C]] 535; 536 %A = mul i8 %x, 5 537 %B = mul i8 %y, 5 538 call void @use(i8 %B) 539 %C = icmp eq i8 %A, %B 540 ret i1 %C 541} 542 543define i1 @mul_constant_ne_extra_use3(i8 %x, i8 %y) { 544; CHECK-LABEL: @mul_constant_ne_extra_use3( 545; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 5 546; CHECK-NEXT: call void @use(i8 [[A]]) 547; CHECK-NEXT: [[B:%.*]] = mul i8 [[Y:%.*]], 5 548; CHECK-NEXT: call void @use(i8 [[B]]) 549; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y]] 550; CHECK-NEXT: ret i1 [[C]] 551; 552 %A = mul i8 %x, 5 553 call void @use(i8 %A) 554 %B = mul i8 %y, 5 555 call void @use(i8 %B) 556 %C = icmp ne i8 %A, %B 557 ret i1 %C 558} 559 560define i1 @mul_constant_eq_nsw(i32 %x, i32 %y) { 561; CHECK-LABEL: @mul_constant_eq_nsw( 562; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] 563; CHECK-NEXT: ret i1 [[C]] 564; 565 %A = mul nsw i32 %x, 6 566 %B = mul nsw i32 %y, 6 567 %C = icmp eq i32 %A, %B 568 ret i1 %C 569} 570 571define <2 x i1> @mul_constant_ne_nsw_splat(<2 x i32> %x, <2 x i32> %y) { 572; CHECK-LABEL: @mul_constant_ne_nsw_splat( 573; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] 574; CHECK-NEXT: ret <2 x i1> [[C]] 575; 576 %A = mul nsw <2 x i32> %x, <i32 12, i32 12> 577 %B = mul nsw <2 x i32> %y, <i32 12, i32 12> 578 %C = icmp ne <2 x i32> %A, %B 579 ret <2 x i1> %C 580} 581 582define i1 @mul_constant_ne_nsw_extra_use1(i8 %x, i8 %y) { 583; CHECK-LABEL: @mul_constant_ne_nsw_extra_use1( 584; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 74 585; CHECK-NEXT: call void @use(i8 [[A]]) 586; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]] 587; CHECK-NEXT: ret i1 [[C]] 588; 589 %A = mul nsw i8 %x, 74 590 call void @use(i8 %A) 591 %B = mul nsw i8 %y, 74 592 %C = icmp ne i8 %A, %B 593 ret i1 %C 594} 595 596define i1 @mul_constant_eq_nsw_extra_use2(i8 %x, i8 %y) { 597; CHECK-LABEL: @mul_constant_eq_nsw_extra_use2( 598; CHECK-NEXT: [[B:%.*]] = mul nsw i8 [[Y:%.*]], 20 599; CHECK-NEXT: call void @use(i8 [[B]]) 600; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]] 601; CHECK-NEXT: ret i1 [[C]] 602; 603 %A = mul nsw i8 %x, 20 604 %B = mul nsw i8 %y, 20 605 call void @use(i8 %B) 606 %C = icmp eq i8 %A, %B 607 ret i1 %C 608} 609 610define i1 @mul_constant_ne_nsw_extra_use3(i8 %x, i8 %y) { 611; CHECK-LABEL: @mul_constant_ne_nsw_extra_use3( 612; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 24 613; CHECK-NEXT: call void @use(i8 [[A]]) 614; CHECK-NEXT: [[B:%.*]] = mul nsw i8 [[Y:%.*]], 24 615; CHECK-NEXT: call void @use(i8 [[B]]) 616; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y]] 617; CHECK-NEXT: ret i1 [[C]] 618; 619 %A = mul nsw i8 %x, 24 620 call void @use(i8 %A) 621 %B = mul nsw i8 %y, 24 622 call void @use(i8 %B) 623 %C = icmp ne i8 %A, %B 624 ret i1 %C 625} 626 627define i1 @mul_constant_nuw_eq(i32 %x, i32 %y) { 628; CHECK-LABEL: @mul_constant_nuw_eq( 629; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] 630; CHECK-NEXT: ret i1 [[C]] 631; 632 %A = mul nuw i32 %x, 22 633 %B = mul nuw i32 %y, 22 634 %C = icmp eq i32 %A, %B 635 ret i1 %C 636} 637 638define <2 x i1> @mul_constant_ne_nuw_splat(<2 x i32> %x, <2 x i32> %y) { 639; CHECK-LABEL: @mul_constant_ne_nuw_splat( 640; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] 641; CHECK-NEXT: ret <2 x i1> [[C]] 642; 643 %A = mul nuw <2 x i32> %x, <i32 10, i32 10> 644 %B = mul nuw <2 x i32> %y, <i32 10, i32 10> 645 %C = icmp ne <2 x i32> %A, %B 646 ret <2 x i1> %C 647} 648 649define i1 @mul_constant_ne_nuw_extra_use1(i8 %x, i8 %y) { 650; CHECK-LABEL: @mul_constant_ne_nuw_extra_use1( 651; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 6 652; CHECK-NEXT: call void @use(i8 [[A]]) 653; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]] 654; CHECK-NEXT: ret i1 [[C]] 655; 656 %A = mul nuw i8 %x, 6 657 call void @use(i8 %A) 658 %B = mul nuw i8 %y, 6 659 %C = icmp ne i8 %A, %B 660 ret i1 %C 661} 662 663define i1 @mul_constant_eq_nuw_extra_use2(i8 %x, i8 %y) { 664; CHECK-LABEL: @mul_constant_eq_nuw_extra_use2( 665; CHECK-NEXT: [[B:%.*]] = mul nuw i8 [[Y:%.*]], 36 666; CHECK-NEXT: call void @use(i8 [[B]]) 667; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]] 668; CHECK-NEXT: ret i1 [[C]] 669; 670 %A = mul nuw i8 %x, 36 671 %B = mul nuw i8 %y, 36 672 call void @use(i8 %B) 673 %C = icmp eq i8 %A, %B 674 ret i1 %C 675} 676 677define i1 @mul_constant_ne_nuw_extra_use3(i8 %x, i8 %y) { 678; CHECK-LABEL: @mul_constant_ne_nuw_extra_use3( 679; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 38 680; CHECK-NEXT: call void @use(i8 [[A]]) 681; CHECK-NEXT: [[B:%.*]] = mul nuw i8 [[Y:%.*]], 38 682; CHECK-NEXT: call void @use(i8 [[B]]) 683; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[X]], [[Y]] 684; CHECK-NEXT: ret i1 [[C]] 685; 686 %A = mul nuw i8 %x, 38 687 call void @use(i8 %A) 688 %B = mul nuw i8 %y, 38 689 call void @use(i8 %B) 690 %C = icmp ne i8 %A, %B 691 ret i1 %C 692} 693 694; Negative test - wrong pred 695 696define i1 @mul_constant_ult(i32 %x, i32 %y) { 697; CHECK-LABEL: @mul_constant_ult( 698; CHECK-NEXT: [[A:%.*]] = mul i32 [[X:%.*]], 47 699; CHECK-NEXT: [[B:%.*]] = mul i32 [[Y:%.*]], 47 700; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A]], [[B]] 701; CHECK-NEXT: ret i1 [[C]] 702; 703 %A = mul i32 %x, 47 704 %B = mul i32 %y, 47 705 %C = icmp ult i32 %A, %B 706 ret i1 %C 707} 708 709; Negative test - wrong pred 710 711define i1 @mul_constant_nuw_sgt(i32 %x, i32 %y) { 712; CHECK-LABEL: @mul_constant_nuw_sgt( 713; CHECK-NEXT: [[A:%.*]] = mul nuw i32 [[X:%.*]], 46 714; CHECK-NEXT: [[B:%.*]] = mul nuw i32 [[Y:%.*]], 46 715; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A]], [[B]] 716; CHECK-NEXT: ret i1 [[C]] 717; 718 %A = mul nuw i32 %x, 46 719 %B = mul nuw i32 %y, 46 720 %C = icmp sgt i32 %A, %B 721 ret i1 %C 722} 723 724; Negative test - wrong constants 725 726define i1 @mul_mismatch_constant_nuw_eq(i32 %x, i32 %y) { 727; CHECK-LABEL: @mul_mismatch_constant_nuw_eq( 728; CHECK-NEXT: [[A:%.*]] = mul nuw i32 [[X:%.*]], 46 729; CHECK-NEXT: [[B:%.*]] = mul nuw i32 [[Y:%.*]], 44 730; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A]], [[B]] 731; CHECK-NEXT: ret i1 [[C]] 732; 733 %A = mul nuw i32 %x, 46 734 %B = mul nuw i32 %y, 44 735 %C = icmp eq i32 %A, %B 736 ret i1 %C 737} 738 739; If the multiply constant has any trailing zero bits but could overflow, 740; we get something completely different. 741; We mask off the high bits of each input and then convert: 742; (X&Z) == (Y&Z) -> (X^Y) & Z == 0 743 744define i1 @mul_constant_partial_nuw_eq(i32 %x, i32 %y) { 745; CHECK-LABEL: @mul_constant_partial_nuw_eq( 746; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] 747; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1073741823 748; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[TMP2]], 0 749; CHECK-NEXT: ret i1 [[C]] 750; 751 %A = mul i32 %x, 44 752 %B = mul nuw i32 %y, 44 753 %C = icmp eq i32 %A, %B 754 ret i1 %C 755} 756 757define i1 @mul_constant_mismatch_wrap_eq(i32 %x, i32 %y) { 758; CHECK-LABEL: @mul_constant_mismatch_wrap_eq( 759; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] 760; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647 761; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[TMP2]], 0 762; CHECK-NEXT: ret i1 [[C]] 763; 764 %A = mul nsw i32 %x, 54 765 %B = mul nuw i32 %y, 54 766 %C = icmp eq i32 %A, %B 767 ret i1 %C 768} 769 770define i1 @eq_mul_constants_with_tz(i32 %x, i32 %y) { 771; CHECK-LABEL: @eq_mul_constants_with_tz( 772; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] 773; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1073741823 774; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP2]], 0 775; CHECK-NEXT: ret i1 [[C]] 776; 777 %A = mul i32 %x, 12 778 %B = mul i32 %y, 12 779 %C = icmp ne i32 %A, %B 780 ret i1 %C 781} 782 783define <2 x i1> @eq_mul_constants_with_tz_splat(<2 x i32> %x, <2 x i32> %y) { 784; CHECK-LABEL: @eq_mul_constants_with_tz_splat( 785; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], [[Y:%.*]] 786; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 1073741823) 787; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer 788; CHECK-NEXT: ret <2 x i1> [[C]] 789; 790 %A = mul <2 x i32> %x, <i32 12, i32 12> 791 %B = mul <2 x i32> %y, <i32 12, i32 12> 792 %C = icmp eq <2 x i32> %A, %B 793 ret <2 x i1> %C 794} 795 796@g = extern_weak global i32 797 798define i1 @oss_fuzz_39934(i32 %arg) { 799; CHECK-LABEL: @oss_fuzz_39934( 800; CHECK-NEXT: [[C10:%.*]] = icmp ne i32 [[ARG:%.*]], 1 801; CHECK-NEXT: ret i1 [[C10]] 802; 803 %B13 = mul nsw i32 %arg, -65536 804 %cmp = icmp eq ptr @g, null 805 %ext = zext i1 %cmp to i32 806 %or = or i32 %ext, 65537 807 %mul = mul i32 %or, -65536 808 %C10 = icmp ne i32 %mul, %B13 809 ret i1 %C10 810} 811 812define i1 @mul_of_bool(i32 %x, i8 %y) { 813; CHECK-LABEL: @mul_of_bool( 814; CHECK-NEXT: ret i1 false 815; 816 %b = and i32 %x, 1 817 %z = zext i8 %y to i32 818 %m = mul i32 %b, %z 819 %r = icmp ugt i32 %m, 255 820 ret i1 %r 821} 822 823define i1 @mul_of_bool_commute(i32 %x, i32 %y) { 824; CHECK-LABEL: @mul_of_bool_commute( 825; CHECK-NEXT: ret i1 false 826; 827 %x1 = and i32 %x, 1 828 %y8 = and i32 %y, 255 829 %m = mul i32 %y8, %x1 830 %r = icmp ugt i32 %m, 255 831 ret i1 %r 832} 833 834define i1 @mul_of_bools(i32 %x, i32 %y) { 835; CHECK-LABEL: @mul_of_bools( 836; CHECK-NEXT: ret i1 true 837; 838 %x1 = and i32 %x, 1 839 %y1 = and i32 %y, 1 840 %m = mul i32 %x1, %y1 841 %r = icmp ult i32 %m, 2 842 ret i1 %r 843} 844 845; negative test - not a mask of low bit 846 847define i1 @not_mul_of_bool(i32 %x, i8 %y) { 848; CHECK-LABEL: @not_mul_of_bool( 849; CHECK-NEXT: [[Q:%.*]] = and i32 [[X:%.*]], 3 850; CHECK-NEXT: [[Z:%.*]] = zext i8 [[Y:%.*]] to i32 851; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[Q]], [[Z]] 852; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[M]], 255 853; CHECK-NEXT: ret i1 [[R]] 854; 855 %q = and i32 %x, 3 856 %z = zext i8 %y to i32 857 %m = mul i32 %q, %z 858 %r = icmp ugt i32 %m, 255 859 ret i1 %r 860} 861 862; negative test - not a single low bit 863 864define i1 @not_mul_of_bool_commute(i32 %x, i32 %y) { 865; CHECK-LABEL: @not_mul_of_bool_commute( 866; CHECK-NEXT: [[X30:%.*]] = lshr i32 [[X:%.*]], 30 867; CHECK-NEXT: [[Y8:%.*]] = and i32 [[Y:%.*]], 255 868; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[Y8]], [[X30]] 869; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[M]], 255 870; CHECK-NEXT: ret i1 [[R]] 871; 872 %x30 = lshr i32 %x, 30 873 %y8 = and i32 %y, 255 874 %m = mul i32 %y8, %x30 875 %r = icmp ugt i32 %m, 255 876 ret i1 %r 877} 878 879; no leading zeros for 's', but we reduce this with other transforms 880 881define i1 @mul_of_bool_no_lz_other_op(i32 %x, i8 %y) { 882; CHECK-LABEL: @mul_of_bool_no_lz_other_op( 883; CHECK-NEXT: ret i1 false 884; 885 %b = and i32 %x, 1 886 %s = sext i8 %y to i32 887 %m = mul nuw nsw i32 %b, %s 888 %r = icmp sgt i32 %m, 127 889 ret i1 %r 890} 891 892; high and low bits are known 0 893 894define i1 @mul_of_pow2(i32 %x, i8 %y) { 895; CHECK-LABEL: @mul_of_pow2( 896; CHECK-NEXT: ret i1 false 897; 898 %b = and i32 %x, 2 899 %z = zext i8 %y to i32 900 %m = mul i32 %b, %z 901 %r = icmp ugt i32 %m, 510 902 ret i1 %r 903} 904 905; high and low bits are known 0 906 907define i1 @mul_of_pow2_commute(i32 %x, i32 %y) { 908; CHECK-LABEL: @mul_of_pow2_commute( 909; CHECK-NEXT: ret i1 false 910; 911 %x4 = and i32 %x, 4 912 %y8 = and i32 %y, 255 913 %m = mul i32 %y8, %x4 914 %r = icmp ugt i32 %m, 1020 915 ret i1 %r 916} 917 918; only bit 7 can be set by the multiply 919 920define i32 @mul_of_pow2s(i32 %x, i32 %y) { 921; CHECK-LABEL: @mul_of_pow2s( 922; CHECK-NEXT: ret i32 128 923; 924 %x8 = and i32 %x, 8 925 %y16 = and i32 %y, 16 926 %m = mul i32 %x8, %y16 927 %bit7 = or i32 %m, 128 928 ret i32 %bit7 929} 930 931; negative test - 6 * 255 = 1530 (but constant range analysis can get this) 932 933define i1 @not_mul_of_pow2(i32 %x, i8 %y) { 934; CHECK-LABEL: @not_mul_of_pow2( 935; CHECK-NEXT: [[Q:%.*]] = and i32 [[X:%.*]], 6 936; CHECK-NEXT: [[Z:%.*]] = zext i8 [[Y:%.*]] to i32 937; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[Q]], [[Z]] 938; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[M]], 1530 939; CHECK-NEXT: ret i1 [[R]] 940; 941 %q = and i32 %x, 6 942 %z = zext i8 %y to i32 943 %m = mul i32 %q, %z 944 %r = icmp ugt i32 %m, 1530 945 ret i1 %r 946} 947 948; negative test - 12 * 255 = 3060 (but constant range analysis can get this) 949 950define i1 @not_mul_of_pow2_commute(i32 %x, i32 %y) { 951; CHECK-LABEL: @not_mul_of_pow2_commute( 952; CHECK-NEXT: [[X30:%.*]] = and i32 [[X:%.*]], 12 953; CHECK-NEXT: [[Y8:%.*]] = and i32 [[Y:%.*]], 255 954; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[Y8]], [[X30]] 955; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[M]], 3060 956; CHECK-NEXT: ret i1 [[R]] 957; 958 %x30 = and i32 %x, 12 959 %y8 = and i32 %y, 255 960 %m = mul i32 %y8, %x30 961 %r = icmp ugt i32 %m, 3060 962 ret i1 %r 963} 964 965; negative test - no leading zeros for 's' 966; TODO: If analysis was generalized for sign bits, we could reduce this to false. 967 968define i1 @mul_of_pow2_no_lz_other_op(i32 %x, i8 %y) { 969; CHECK-LABEL: @mul_of_pow2_no_lz_other_op( 970; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 2 971; CHECK-NEXT: [[S:%.*]] = sext i8 [[Y:%.*]] to i32 972; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[B]], [[S]] 973; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[M]], 254 974; CHECK-NEXT: ret i1 [[R]] 975; 976 %b = and i32 %x, 2 977 %s = sext i8 %y to i32 978 %m = mul nuw nsw i32 %b, %s 979 %r = icmp sgt i32 %m, 254 980 ret i1 %r 981} 982 983; The top 32-bits must be zero. 984 985define i1 @splat_mul_known_lz(i32 %x) { 986; CHECK-LABEL: @splat_mul_known_lz( 987; CHECK-NEXT: ret i1 true 988; 989 %z = zext i32 %x to i128 990 %m = mul i128 %z, 18446744078004518913 ; 0x00000000_00000001_00000001_00000001 991 %s = lshr i128 %m, 96 992 %r = icmp eq i128 %s, 0 993 ret i1 %r 994} 995 996; The 33rd bit can only be set when MSB of x is set. 997 998define i1 @splat_mul_unknown_lz(i32 %x) { 999; CHECK-LABEL: @splat_mul_unknown_lz( 1000; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[X:%.*]], -1 1001; CHECK-NEXT: ret i1 [[R]] 1002; 1003 %z = zext i32 %x to i128 1004 %m = mul i128 %z, 18446744078004518913 ; 0x00000000_00000001_00000001_00000001 1005 %s = lshr i128 %m, 95 1006 %r = icmp eq i128 %s, 0 1007 ret i1 %r 1008} 1009 1010define i1 @mul_oddC_overflow_eq(i8 %v) { 1011; CHECK-LABEL: @mul_oddC_overflow_eq( 1012; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[V:%.*]], 5 1013; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL]], 101 1014; CHECK-NEXT: ret i1 [[CMP]] 1015; 1016 %mul = mul i8 %v, 5 1017 %cmp = icmp eq i8 %mul, 101 1018 ret i1 %cmp 1019} 1020 1021define i1 @mul_oddC_eq_nomod(i8 %v) { 1022; CHECK-LABEL: @mul_oddC_eq_nomod( 1023; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[V:%.*]], 3 1024; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL]], 34 1025; CHECK-NEXT: ret i1 [[CMP]] 1026; 1027 %mul = mul i8 %v, 3 1028 %cmp = icmp eq i8 %mul, 34 1029 ret i1 %cmp 1030} 1031 1032define i1 @mul_evenC_ne(i8 %v) { 1033; CHECK-LABEL: @mul_evenC_ne( 1034; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[V:%.*]], 6 1035; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[MUL]], 36 1036; CHECK-NEXT: ret i1 [[CMP]] 1037; 1038 %mul = mul i8 %v, 6 1039 %cmp = icmp ne i8 %mul, 36 1040 ret i1 %cmp 1041} 1042 1043define <2 x i1> @mul_oddC_ne_vec(<2 x i8> %v) { 1044; CHECK-LABEL: @mul_oddC_ne_vec( 1045; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[V:%.*]], splat (i8 4) 1046; CHECK-NEXT: ret <2 x i1> [[CMP]] 1047; 1048 %mul = mul <2 x i8> %v, <i8 3, i8 3> 1049 %cmp = icmp ne <2 x i8> %mul, <i8 12, i8 12> 1050 ret <2 x i1> %cmp 1051} 1052 1053define <2 x i1> @mul_oddC_ne_nosplat_vec(<2 x i8> %v) { 1054; CHECK-LABEL: @mul_oddC_ne_nosplat_vec( 1055; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i8> [[V:%.*]], <i8 3, i8 5> 1056; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[MUL]], <i8 12, i8 15> 1057; CHECK-NEXT: ret <2 x i1> [[CMP]] 1058; 1059 %mul = mul <2 x i8> %v, <i8 3, i8 5> 1060 %cmp = icmp ne <2 x i8> %mul, <i8 12, i8 15> 1061 ret <2 x i1> %cmp 1062} 1063 1064define i1 @mul_nsuw_xy_z_maybe_zero_eq(i8 %x, i8 %y, i8 %z) { 1065; CHECK-LABEL: @mul_nsuw_xy_z_maybe_zero_eq( 1066; CHECK-NEXT: [[MULX:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Z:%.*]] 1067; CHECK-NEXT: [[MULY:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[Z]] 1068; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MULX]], [[MULY]] 1069; CHECK-NEXT: ret i1 [[CMP]] 1070; 1071 %mulx = mul nsw nuw i8 %x, %z 1072 %muly = mul nsw nuw i8 %y, %z 1073 %cmp = icmp eq i8 %mulx, %muly 1074 ret i1 %cmp 1075} 1076 1077define i1 @mul_xy_z_assumenozero_ne(i8 %x, i8 %y, i8 %z) { 1078; CHECK-LABEL: @mul_xy_z_assumenozero_ne( 1079; CHECK-NEXT: [[NZ:%.*]] = icmp ne i8 [[Z:%.*]], 0 1080; CHECK-NEXT: call void @llvm.assume(i1 [[NZ]]) 1081; CHECK-NEXT: [[MULX:%.*]] = mul i8 [[X:%.*]], [[Z]] 1082; CHECK-NEXT: [[MULY:%.*]] = mul i8 [[Y:%.*]], [[Z]] 1083; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[MULY]], [[MULX]] 1084; CHECK-NEXT: ret i1 [[CMP]] 1085; 1086 %nz = icmp ne i8 %z, 0 1087 call void @llvm.assume(i1 %nz) 1088 %mulx = mul i8 %x, %z 1089 %muly = mul i8 %y, %z 1090 %cmp = icmp ne i8 %muly, %mulx 1091 ret i1 %cmp 1092} 1093 1094define i1 @mul_xy_z_assumeodd_eq(i8 %x, i8 %y, i8 %z) { 1095; CHECK-LABEL: @mul_xy_z_assumeodd_eq( 1096; CHECK-NEXT: [[LB:%.*]] = and i8 [[Z:%.*]], 1 1097; CHECK-NEXT: [[NZ:%.*]] = icmp ne i8 [[LB]], 0 1098; CHECK-NEXT: call void @llvm.assume(i1 [[NZ]]) 1099; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]] 1100; CHECK-NEXT: ret i1 [[CMP]] 1101; 1102 %lb = and i8 %z, 1 1103 %nz = icmp ne i8 %lb, 0 1104 call void @llvm.assume(i1 %nz) 1105 %mulx = mul i8 %x, %z 1106 %muly = mul i8 %z, %y 1107 %cmp = icmp eq i8 %mulx, %muly 1108 ret i1 %cmp 1109} 1110 1111define <2 x i1> @reused_mul_nsw_xy_z_setnonzero_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) { 1112; CHECK-LABEL: @reused_mul_nsw_xy_z_setnonzero_vec_ne( 1113; CHECK-NEXT: [[Z:%.*]] = or <2 x i8> [[ZI:%.*]], splat (i8 4) 1114; CHECK-NEXT: [[MULY:%.*]] = mul nsw <2 x i8> [[Y:%.*]], [[Z]] 1115; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[Y]], [[X:%.*]] 1116; CHECK-NEXT: call void @usev2xi8(<2 x i8> [[MULY]]) 1117; CHECK-NEXT: ret <2 x i1> [[CMP]] 1118; 1119 %z = or <2 x i8> %zi, <i8 4, i8 4> 1120 %mulx = mul nsw <2 x i8> %z, %x 1121 %muly = mul nsw <2 x i8> %y, %z 1122 %cmp = icmp ne <2 x i8> %muly, %mulx 1123 call void @usev2xi8(<2 x i8> %muly) 1124 ret <2 x i1> %cmp 1125} 1126 1127define i1 @mul_mixed_nuw_nsw_xy_z_setodd_ult(i8 %x, i8 %y, i8 %zi) { 1128; CHECK-LABEL: @mul_mixed_nuw_nsw_xy_z_setodd_ult( 1129; CHECK-NEXT: [[Z:%.*]] = or i8 [[ZI:%.*]], 1 1130; CHECK-NEXT: [[MULX:%.*]] = mul nsw i8 [[X:%.*]], [[Z]] 1131; CHECK-NEXT: [[MULY:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[Z]] 1132; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[MULX]], [[MULY]] 1133; CHECK-NEXT: ret i1 [[CMP]] 1134; 1135 %z = or i8 %zi, 1 1136 %mulx = mul nsw i8 %x, %z 1137 %muly = mul nuw nsw i8 %y, %z 1138 %cmp = icmp ult i8 %mulx, %muly 1139 ret i1 %cmp 1140} 1141 1142define i1 @mul_nuw_xy_z_assumenonzero_uge(i8 %x, i8 %y, i8 %z) { 1143; CHECK-LABEL: @mul_nuw_xy_z_assumenonzero_uge( 1144; CHECK-NEXT: [[NZ:%.*]] = icmp ne i8 [[Z:%.*]], 0 1145; CHECK-NEXT: call void @llvm.assume(i1 [[NZ]]) 1146; CHECK-NEXT: [[MULX:%.*]] = mul nuw i8 [[X:%.*]], [[Z]] 1147; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[Y:%.*]], [[X]] 1148; CHECK-NEXT: call void @use(i8 [[MULX]]) 1149; CHECK-NEXT: ret i1 [[CMP]] 1150; 1151 %nz = icmp ne i8 %z, 0 1152 call void @llvm.assume(i1 %nz) 1153 %mulx = mul nuw i8 %x, %z 1154 %muly = mul nuw i8 %y, %z 1155 %cmp = icmp uge i8 %muly, %mulx 1156 call void @use(i8 %mulx) 1157 ret i1 %cmp 1158} 1159 1160define <2 x i1> @mul_nuw_xy_z_setnonzero_vec_eq(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) { 1161; CHECK-LABEL: @mul_nuw_xy_z_setnonzero_vec_eq( 1162; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], [[Y:%.*]] 1163; CHECK-NEXT: ret <2 x i1> [[CMP]] 1164; 1165 %z = or <2 x i8> %zi, <i8 41, i8 12> 1166 %mulx = mul nuw <2 x i8> %z, %x 1167 %muly = mul nuw <2 x i8> %z, %y 1168 %cmp = icmp eq <2 x i8> %mulx, %muly 1169 ret <2 x i1> %cmp 1170} 1171 1172define i1 @mul_nuw_xy_z_brnonzero_ult(i8 %x, i8 %y, i8 %z) { 1173; CHECK-LABEL: @mul_nuw_xy_z_brnonzero_ult( 1174; CHECK-NEXT: [[NZ_NOT:%.*]] = icmp eq i8 [[Z:%.*]], 0 1175; CHECK-NEXT: br i1 [[NZ_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]] 1176; CHECK: true: 1177; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[Y:%.*]], [[X:%.*]] 1178; CHECK-NEXT: ret i1 [[CMP]] 1179; CHECK: false: 1180; CHECK-NEXT: call void @use(i8 [[Z]]) 1181; CHECK-NEXT: ret i1 true 1182; 1183 %nz = icmp ne i8 %z, 0 1184 br i1 %nz, label %true, label %false 1185true: 1186 %mulx = mul nuw i8 %x, %z 1187 %muly = mul nuw i8 %y, %z 1188 %cmp = icmp ult i8 %muly, %mulx 1189 ret i1 %cmp 1190false: 1191 call void @use(i8 %z) 1192 ret i1 true 1193} 1194 1195define i1 @reused_mul_nuw_xy_z_selectnonzero_ugt(i8 %x, i8 %y, i8 %z) { 1196; CHECK-LABEL: @reused_mul_nuw_xy_z_selectnonzero_ugt( 1197; CHECK-NEXT: [[NZ_NOT:%.*]] = icmp eq i8 [[Z:%.*]], 0 1198; CHECK-NEXT: [[MULX:%.*]] = mul nuw i8 [[X:%.*]], [[Z]] 1199; CHECK-NEXT: [[MULY:%.*]] = mul nuw i8 [[Y:%.*]], [[Z]] 1200; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[MULY]], [[MULX]] 1201; CHECK-NEXT: [[R:%.*]] = select i1 [[NZ_NOT]], i1 true, i1 [[CMP]] 1202; CHECK-NEXT: ret i1 [[R]] 1203; 1204 %nz = icmp ne i8 %z, 0 1205 %mulx = mul nuw i8 %x, %z 1206 %muly = mul nuw i8 %y, %z 1207 %cmp = icmp ugt i8 %muly, %mulx 1208 %r = select i1 %nz, i1 %cmp, i1 true 1209 ret i1 %r 1210} 1211 1212define <2 x i1> @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) { 1213; CHECK-LABEL: @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule( 1214; CHECK-NEXT: [[Z:%.*]] = or <2 x i8> [[ZI:%.*]], <i8 1, i8 3> 1215; CHECK-NEXT: [[MULX:%.*]] = mul nuw <2 x i8> [[X:%.*]], [[Z]] 1216; CHECK-NEXT: [[MULY:%.*]] = mul nsw <2 x i8> [[Z]], [[Y:%.*]] 1217; CHECK-NEXT: [[CMP:%.*]] = icmp ule <2 x i8> [[MULY]], [[MULX]] 1218; CHECK-NEXT: ret <2 x i1> [[CMP]] 1219; 1220 %z = or <2 x i8> %zi, <i8 1, i8 3> 1221 %mulx = mul nuw <2 x i8> %x, %z 1222 %muly = mul nsw <2 x i8> %z, %y 1223 %cmp = icmp ule <2 x i8> %muly, %mulx 1224 ret <2 x i1> %cmp 1225} 1226 1227define i1 @icmp_eq_mul_nsw_nonequal(i8 %a, i8 %c) { 1228; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal( 1229; CHECK-NEXT: entry: 1230; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0 1231; CHECK-NEXT: ret i1 [[CMP]] 1232; 1233entry: 1234 %b = add i8 %a, 1 1235 %mul1 = mul nsw i8 %a, %c 1236 %mul2 = mul nsw i8 %b, %c 1237 %cmp = icmp eq i8 %mul1, %mul2 1238 ret i1 %cmp 1239} 1240 1241define i1 @icmp_eq_mul_nuw_nonequal(i8 %a, i8 %c) { 1242; CHECK-LABEL: @icmp_eq_mul_nuw_nonequal( 1243; CHECK-NEXT: entry: 1244; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0 1245; CHECK-NEXT: ret i1 [[CMP]] 1246; 1247entry: 1248 %b = add i8 %a, 1 1249 %mul1 = mul nuw i8 %a, %c 1250 %mul2 = mul nuw i8 %b, %c 1251 %cmp = icmp eq i8 %mul1, %mul2 1252 ret i1 %cmp 1253} 1254 1255define i1 @icmp_eq_mul_nsw_nonequal_commuted(i8 %a, i8 %c) { 1256; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal_commuted( 1257; CHECK-NEXT: entry: 1258; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0 1259; CHECK-NEXT: ret i1 [[CMP]] 1260; 1261entry: 1262 %b = add i8 %a, 1 1263 %mul1 = mul nsw i8 %a, %c 1264 %mul2 = mul nsw i8 %c, %b 1265 %cmp = icmp eq i8 %mul1, %mul2 1266 ret i1 %cmp 1267} 1268 1269define i1 @icmp_ne_mul_nsw_nonequal(i8 %a, i8 %c) { 1270; CHECK-LABEL: @icmp_ne_mul_nsw_nonequal( 1271; CHECK-NEXT: entry: 1272; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[C:%.*]], 0 1273; CHECK-NEXT: ret i1 [[CMP]] 1274; 1275entry: 1276 %b = add i8 %a, 1 1277 %mul1 = mul nsw i8 %a, %c 1278 %mul2 = mul nsw i8 %b, %c 1279 %cmp = icmp ne i8 %mul1, %mul2 1280 ret i1 %cmp 1281} 1282 1283; Negative tests 1284 1285define i1 @icmp_eq_mul_nsw_mayequal(i8 %a, i8 %b, i8 %c) { 1286; CHECK-LABEL: @icmp_eq_mul_nsw_mayequal( 1287; CHECK-NEXT: entry: 1288; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[C:%.*]] 1289; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B:%.*]], [[C]] 1290; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]] 1291; CHECK-NEXT: ret i1 [[CMP]] 1292; 1293entry: 1294 %mul1 = mul nsw i8 %a, %c 1295 %mul2 = mul nsw i8 %b, %c 1296 %cmp = icmp eq i8 %mul1, %mul2 1297 ret i1 %cmp 1298} 1299 1300define i1 @icmp_eq_mul_nsw_nuw_nonequal(i8 %a, i8 %c) { 1301; CHECK-LABEL: @icmp_eq_mul_nsw_nuw_nonequal( 1302; CHECK-NEXT: entry: 1303; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1 1304; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]] 1305; CHECK-NEXT: [[MUL2:%.*]] = mul nuw i8 [[B]], [[C]] 1306; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]] 1307; CHECK-NEXT: ret i1 [[CMP]] 1308; 1309entry: 1310 %b = add i8 %a, 1 1311 %mul1 = mul nsw i8 %a, %c 1312 %mul2 = mul nuw i8 %b, %c 1313 %cmp = icmp eq i8 %mul1, %mul2 1314 ret i1 %cmp 1315} 1316 1317define i1 @icmp_ult_mul_nsw_nonequal(i8 %a, i8 %c) { 1318; CHECK-LABEL: @icmp_ult_mul_nsw_nonequal( 1319; CHECK-NEXT: entry: 1320; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1 1321; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]] 1322; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]] 1323; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[MUL1]], [[MUL2]] 1324; CHECK-NEXT: ret i1 [[CMP]] 1325; 1326entry: 1327 %b = add i8 %a, 1 1328 %mul1 = mul nsw i8 %a, %c 1329 %mul2 = mul nsw i8 %b, %c 1330 %cmp = icmp ult i8 %mul1, %mul2 1331 ret i1 %cmp 1332} 1333 1334define i1 @icmp_mul_nsw_slt(i8 %x, i8 %y) { 1335; CHECK-LABEL: @icmp_mul_nsw_slt( 1336; CHECK-NEXT: entry: 1337; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] 1338; CHECK-NEXT: ret i1 [[CMP]] 1339; 1340entry: 1341 %mul1 = mul nsw i8 %x, 7 1342 %mul2 = mul nsw i8 %y, 7 1343 %cmp = icmp slt i8 %mul1, %mul2 1344 ret i1 %cmp 1345} 1346 1347define i1 @icmp_mul_nsw_sle(i8 %x, i8 %y) { 1348; CHECK-LABEL: @icmp_mul_nsw_sle( 1349; CHECK-NEXT: entry: 1350; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] 1351; CHECK-NEXT: ret i1 [[CMP]] 1352; 1353entry: 1354 %mul1 = mul nsw i8 %x, 7 1355 %mul2 = mul nsw i8 %y, 7 1356 %cmp = icmp sle i8 %mul1, %mul2 1357 ret i1 %cmp 1358} 1359 1360define i1 @icmp_mul_nsw_sgt(i8 %x, i8 %y) { 1361; CHECK-LABEL: @icmp_mul_nsw_sgt( 1362; CHECK-NEXT: entry: 1363; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] 1364; CHECK-NEXT: ret i1 [[CMP]] 1365; 1366entry: 1367 %mul1 = mul nsw i8 %x, 7 1368 %mul2 = mul nsw i8 %y, 7 1369 %cmp = icmp sgt i8 %mul1, %mul2 1370 ret i1 %cmp 1371} 1372 1373define i1 @icmp_mul_nsw_sge(i8 %x, i8 %y) { 1374; CHECK-LABEL: @icmp_mul_nsw_sge( 1375; CHECK-NEXT: entry: 1376; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] 1377; CHECK-NEXT: ret i1 [[CMP]] 1378; 1379entry: 1380 %mul1 = mul nsw i8 %x, 7 1381 %mul2 = mul nsw i8 %y, 7 1382 %cmp = icmp sge i8 %mul1, %mul2 1383 ret i1 %cmp 1384} 1385 1386define i1 @icmp_mul_nsw_slt_neg(i8 %x, i8 %y) { 1387; CHECK-LABEL: @icmp_mul_nsw_slt_neg( 1388; CHECK-NEXT: entry: 1389; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] 1390; CHECK-NEXT: ret i1 [[CMP]] 1391; 1392entry: 1393 %mul1 = mul nsw i8 %x, -7 1394 %mul2 = mul nsw i8 %y, -7 1395 %cmp = icmp slt i8 %mul1, %mul2 1396 ret i1 %cmp 1397} 1398 1399define i1 @icmp_mul_nsw_slt_neg_var(i8 %x, i8 %y, i8 %z) { 1400; CHECK-LABEL: @icmp_mul_nsw_slt_neg_var( 1401; CHECK-NEXT: entry: 1402; CHECK-NEXT: [[COND:%.*]] = icmp slt i8 [[Z:%.*]], 0 1403; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) 1404; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] 1405; CHECK-NEXT: ret i1 [[CMP]] 1406; 1407entry: 1408 %cond = icmp slt i8 %z, 0 1409 call void @llvm.assume(i1 %cond) 1410 %mul1 = mul nsw i8 %x, %z 1411 %mul2 = mul nsw i8 %y, %z 1412 %cmp = icmp slt i8 %mul1, %mul2 1413 ret i1 %cmp 1414} 1415 1416; Negative tests 1417 1418define i1 @icmp_mul_nonsw_slt(i8 %x, i8 %y) { 1419; CHECK-LABEL: @icmp_mul_nonsw_slt( 1420; CHECK-NEXT: entry: 1421; CHECK-NEXT: [[MUL1:%.*]] = mul i8 [[X:%.*]], 7 1422; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], 7 1423; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]] 1424; CHECK-NEXT: ret i1 [[CMP]] 1425; 1426entry: 1427 %mul1 = mul i8 %x, 7 1428 %mul2 = mul nsw i8 %y, 7 1429 %cmp = icmp slt i8 %mul1, %mul2 1430 ret i1 %cmp 1431} 1432 1433define i1 @icmp_mul_nsw_slt_unknown_sign(i8 %x, i8 %y, i8 %z) { 1434; CHECK-LABEL: @icmp_mul_nsw_slt_unknown_sign( 1435; CHECK-NEXT: entry: 1436; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[X:%.*]], [[Z:%.*]] 1437; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], [[Z]] 1438; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]] 1439; CHECK-NEXT: ret i1 [[CMP]] 1440; 1441entry: 1442 %mul1 = mul nsw i8 %x, %z 1443 %mul2 = mul nsw i8 %y, %z 1444 %cmp = icmp slt i8 %mul1, %mul2 1445 ret i1 %cmp 1446} 1447 1448define i1 @icmp_mul_nsw_slt_may_be_zero(i8 %x, i8 %y, i8 %z) { 1449; CHECK-LABEL: @icmp_mul_nsw_slt_may_be_zero( 1450; CHECK-NEXT: entry: 1451; CHECK-NEXT: [[COND:%.*]] = icmp sgt i8 [[Z:%.*]], -1 1452; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) 1453; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[X:%.*]], [[Z]] 1454; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], [[Z]] 1455; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]] 1456; CHECK-NEXT: ret i1 [[CMP]] 1457; 1458entry: 1459 %cond = icmp sgt i8 %z, -1 1460 call void @llvm.assume(i1 %cond) 1461 1462 %mul1 = mul nsw i8 %x, %z 1463 %mul2 = mul nsw i8 %y, %z 1464 %cmp = icmp slt i8 %mul1, %mul2 1465 ret i1 %cmp 1466} 1467 1468define i1 @test_icmp_slt_mul_known_sgt(i64 %x, i64 %z) { 1469; CHECK-LABEL: @test_icmp_slt_mul_known_sgt( 1470; CHECK-NEXT: entry: 1471; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 1472; CHECK-NEXT: ret i1 [[CMP]] 1473; 1474entry: 1475 %y = add nsw i64 %x, 1 1476 %mul1 = mul nsw i64 %x, %z 1477 %mul2 = mul nsw i64 %y, %z 1478 %cmp = icmp slt i64 %mul1, %mul2 1479 ret i1 %cmp 1480} 1481 1482define i1 @test_icmp_sle_mul_known_sgt(i64 %x, i64 %z) { 1483; CHECK-LABEL: @test_icmp_sle_mul_known_sgt( 1484; CHECK-NEXT: entry: 1485; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], -1 1486; CHECK-NEXT: ret i1 [[CMP]] 1487; 1488entry: 1489 %y = add nsw i64 %x, 1 1490 %mul1 = mul nsw i64 %x, %z 1491 %mul2 = mul nsw i64 %y, %z 1492 %cmp = icmp sle i64 %mul1, %mul2 1493 ret i1 %cmp 1494} 1495 1496define i1 @test_icmp_mul_known_slt(i64 %x, i64 %z) { 1497; CHECK-LABEL: @test_icmp_mul_known_slt( 1498; CHECK-NEXT: entry: 1499; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[Z:%.*]], 0 1500; CHECK-NEXT: ret i1 [[CMP]] 1501; 1502entry: 1503 %y = add nsw i64 %x, 1 1504 %mul1 = mul nsw i64 %x, %z 1505 %mul2 = mul nsw i64 %y, %z 1506 %cmp = icmp slt i64 %mul2, %mul1 1507 ret i1 %cmp 1508} 1509 1510define i1 @test_icmp_slt_mul_known_sgt_commuted1(i64 %x, i64 %z) { 1511; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted1( 1512; CHECK-NEXT: entry: 1513; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 1514; CHECK-NEXT: ret i1 [[CMP]] 1515; 1516entry: 1517 %y = add nsw i64 %x, 1 1518 %mul1 = mul nsw i64 %z, %x 1519 %mul2 = mul nsw i64 %y, %z 1520 %cmp = icmp slt i64 %mul1, %mul2 1521 ret i1 %cmp 1522} 1523 1524define i1 @test_icmp_slt_mul_known_sgt_commuted2(i64 %x, i64 %z) { 1525; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted2( 1526; CHECK-NEXT: entry: 1527; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 1528; CHECK-NEXT: ret i1 [[CMP]] 1529; 1530entry: 1531 %y = add nsw i64 %x, 1 1532 %mul1 = mul nsw i64 %x, %z 1533 %mul2 = mul nsw i64 %z, %y 1534 %cmp = icmp slt i64 %mul1, %mul2 1535 ret i1 %cmp 1536} 1537 1538define i1 @test_icmp_slt_mul_unknown(i64 %x, i64 %z) { 1539; CHECK-LABEL: @test_icmp_slt_mul_unknown( 1540; CHECK-NEXT: entry: 1541; CHECK-NEXT: [[Y:%.*]] = add i64 [[X:%.*]], 1 1542; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i64 [[X]], [[Z:%.*]] 1543; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]] 1544; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]] 1545; CHECK-NEXT: ret i1 [[CMP]] 1546; 1547entry: 1548 %y = add i64 %x, 1 1549 %mul1 = mul nsw i64 %x, %z 1550 %mul2 = mul nsw i64 %z, %y 1551 %cmp = icmp slt i64 %mul1, %mul2 1552 ret i1 %cmp 1553} 1554 1555define i1 @test_icmp_slt_mul_no_nsw(i64 %x, i64 %z) { 1556; CHECK-LABEL: @test_icmp_slt_mul_no_nsw( 1557; CHECK-NEXT: entry: 1558; CHECK-NEXT: [[Y:%.*]] = add nsw i64 [[X:%.*]], 1 1559; CHECK-NEXT: [[MUL1:%.*]] = mul i64 [[X]], [[Z:%.*]] 1560; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]] 1561; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]] 1562; CHECK-NEXT: ret i1 [[CMP]] 1563; 1564entry: 1565 %y = add nsw i64 %x, 1 1566 %mul1 = mul i64 %x, %z 1567 %mul2 = mul nsw i64 %z, %y 1568 %cmp = icmp slt i64 %mul1, %mul2 1569 ret i1 %cmp 1570} 1571