1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4; A == B implies A >u B is false. 5 6define void @test1(i32 %a, i32 %b) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 9; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 10; CHECK: taken: 11; CHECK-NEXT: call void @foo(i32 10) 12; CHECK-NEXT: br label [[END]] 13; CHECK: end: 14; CHECK-NEXT: ret void 15; 16 %cmp1 = icmp eq i32 %a, %b 17 br i1 %cmp1, label %taken, label %end 18 19taken: 20 %cmp2 = icmp ugt i32 %a, %b 21 %c = select i1 %cmp2, i32 0, i32 10 22 call void @foo(i32 %c) 23 br label %end 24 25end: 26 ret void 27} 28 29; If A == B is false then A != B is true. 30 31define void @test2(i32 %a, i32 %b) { 32; CHECK-LABEL: @test2( 33; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 34; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 35; CHECK: taken: 36; CHECK-NEXT: call void @foo(i32 20) 37; CHECK-NEXT: br label [[END]] 38; CHECK: end: 39; CHECK-NEXT: ret void 40; 41 %cmp1 = icmp eq i32 %a, %b 42 br i1 %cmp1, label %end, label %taken 43 44taken: 45 %cmp2 = icmp ne i32 %a, %b 46 %c = select i1 %cmp2, i32 20, i32 0 47 call void @foo(i32 %c) 48 br label %end 49 50end: 51 ret void 52} 53 54; A >u 10 implies A >u 10 is true. 55 56define void @test3(i32 %a) { 57; CHECK-LABEL: @test3( 58; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10 59; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 60; CHECK: taken: 61; CHECK-NEXT: call void @foo(i32 30) 62; CHECK-NEXT: br label [[END]] 63; CHECK: end: 64; CHECK-NEXT: ret void 65; 66 %cmp1 = icmp ugt i32 %a, 10 67 br i1 %cmp1, label %taken, label %end 68 69taken: 70 %cmp2 = icmp ugt i32 %a, 10 71 %c = select i1 %cmp2, i32 30, i32 0 72 call void @foo(i32 %c) 73 br label %end 74 75end: 76 ret void 77} 78 79define i8 @PR23333(ptr addrspace(1) %ptr) { 80; CHECK-LABEL: @PR23333( 81; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[PTR:%.*]], null 82; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[END:%.*]] 83; CHECK: taken: 84; CHECK-NEXT: ret i8 1 85; CHECK: end: 86; CHECK-NEXT: ret i8 0 87; 88 %cmp = icmp eq ptr addrspace(1) %ptr, null 89 br i1 %cmp, label %taken, label %end 90 91taken: 92 %cmp2 = icmp ne ptr addrspace(1) %ptr, null 93 %res = select i1 %cmp2, i8 2, i8 1 94 ret i8 %res 95 96end: 97 ret i8 0 98} 99 100; We know the condition of the select is true based on a dominating condition. 101; Therefore, we can replace %cond with %len. 102; TODO: len == 8 is known false in bb. This is handled by other passes, but should it be handled here? 103 104define void @test4(i32 %len) { 105; CHECK-LABEL: @test4( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: [[TMP0:%.*]] = call i32 @bar(i32 [[LEN:%.*]]) 108; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LEN]], 4 109; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[B1:%.*]] 110; CHECK: bb: 111; CHECK-NEXT: [[CMP11:%.*]] = icmp eq i32 [[LEN]], 8 112; CHECK-NEXT: br i1 [[CMP11]], label [[B0:%.*]], label [[B1]] 113; CHECK: b0: 114; CHECK-NEXT: call void @foo(i32 [[LEN]]) 115; CHECK-NEXT: br label [[B1]] 116; CHECK: b1: 117; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 118; CHECK-NEXT: br label [[RET:%.*]] 119; CHECK: ret: 120; CHECK-NEXT: call void @foo(i32 [[TMP1]]) 121; CHECK-NEXT: ret void 122; 123entry: 124 %0 = call i32 @bar(i32 %len); 125 %cmp = icmp ult i32 %len, 4 126 br i1 %cmp, label %bb, label %b1 127bb: 128 %cond = select i1 %cmp, i32 %len, i32 8 129 %cmp11 = icmp eq i32 %cond, 8 130 br i1 %cmp11, label %b0, label %b1 131 132b0: 133 call void @foo(i32 %len) 134 br label %b1 135 136b1: 137 %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] 138 br label %ret 139 140ret: 141 call void @foo(i32 %1) 142 ret void 143} 144 145; A >u 10 implies A >u 9 is true. 146 147define void @test5(i32 %a) { 148; CHECK-LABEL: @test5( 149; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10 150; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 151; CHECK: taken: 152; CHECK-NEXT: call void @foo(i32 30) 153; CHECK-NEXT: br label [[END]] 154; CHECK: end: 155; CHECK-NEXT: ret void 156; 157 %cmp1 = icmp ugt i32 %a, 10 158 br i1 %cmp1, label %taken, label %end 159 160taken: 161 %cmp2 = icmp ugt i32 %a, 9 162 %c = select i1 %cmp2, i32 30, i32 0 163 call void @foo(i32 %c) 164 br label %end 165 166end: 167 ret void 168} 169 170declare void @foo(i32) 171declare i32 @bar(i32) 172 173define i32 @test_and(i32 %a, i32 %b) { 174; CHECK-LABEL: @test_and( 175; CHECK-NEXT: entry: 176; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0 177; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0 178; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 179; CHECK-NEXT: br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]] 180; CHECK: tpath: 181; CHECK-NEXT: ret i32 313 182; CHECK: end: 183; CHECK-NEXT: ret i32 0 184; 185entry: 186 %cmp1 = icmp ne i32 %a, 0 187 %cmp2 = icmp ne i32 %b, 0 188 %and = and i1 %cmp1, %cmp2 189 br i1 %and, label %tpath, label %end 190 191tpath: 192 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false 193 %c = select i1 %cmp3, i32 0, i32 313 194 ret i32 %c 195 196end: 197 ret i32 0 198} 199 200; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true. 201 202define i32 @test_or1(i32 %a, i32 %b) { 203; CHECK-LABEL: @test_or1( 204; CHECK-NEXT: entry: 205; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 206; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 207; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 208; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]] 209; CHECK: fpath: 210; CHECK-NEXT: ret i32 37 211; CHECK: end: 212; CHECK-NEXT: ret i32 0 213; 214entry: 215 %cmp1 = icmp eq i32 %a, 0 216 %cmp2 = icmp eq i32 %b, 0 217 %or = or i1 %cmp1, %cmp2 218 br i1 %or, label %end, label %fpath 219 220fpath: 221 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true 222 %c = select i1 %cmp3, i32 37, i32 0 223 ret i32 %c 224 225end: 226 ret i32 0 227} 228 229; LHS ==> RHS by definition (true -> true) 230 231define void @test6(i32 %a, i32 %b) { 232; CHECK-LABEL: @test6( 233; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 234; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 235; CHECK: taken: 236; CHECK-NEXT: call void @foo(i32 10) 237; CHECK-NEXT: br label [[END]] 238; CHECK: end: 239; CHECK-NEXT: ret void 240; 241 %cmp1 = icmp eq i32 %a, %b 242 br i1 %cmp1, label %taken, label %end 243 244taken: 245 %c = select i1 %cmp1, i32 10, i32 0 246 call void @foo(i32 %c) 247 br label %end 248 249end: 250 ret void 251} 252 253; LHS ==> RHS by definition (false -> false) 254 255define void @test7(i32 %a, i32 %b) { 256; CHECK-LABEL: @test7( 257; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 258; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 259; CHECK: taken: 260; CHECK-NEXT: call void @foo(i32 11) 261; CHECK-NEXT: br label [[END]] 262; CHECK: end: 263; CHECK-NEXT: ret void 264; 265 %cmp1 = icmp eq i32 %a, %b 266 br i1 %cmp1, label %end, label %taken 267 268taken: 269 %c = select i1 %cmp1, i32 0, i32 11 270 call void @foo(i32 %c) 271 br label %end 272 273end: 274 ret void 275} 276 277define void @implies_or(i32 %a, i32 %b, i1 %x) { 278; CHECK-LABEL: @implies_or( 279; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 280; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 281; CHECK: taken: 282; CHECK-NEXT: call void @foo(i32 20) 283; CHECK-NEXT: br label [[END]] 284; CHECK: end: 285; CHECK-NEXT: ret void 286; 287 %cmp1 = icmp eq i32 %a, %b 288 br i1 %cmp1, label %end, label %taken 289 290taken: 291 %cmp2 = icmp ne i32 %a, %b 292 %or = or i1 %cmp2, %x 293 %c = select i1 %or, i32 20, i32 0 294 call void @foo(i32 %c) 295 br label %end 296 297end: 298 ret void 299} 300 301define void @implies_or_comm(i32 %a, i32 %b, i1 %x) { 302; CHECK-LABEL: @implies_or_comm( 303; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 304; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 305; CHECK: taken: 306; CHECK-NEXT: call void @foo(i32 20) 307; CHECK-NEXT: br label [[END]] 308; CHECK: end: 309; CHECK-NEXT: ret void 310; 311 %cmp1 = icmp eq i32 %a, %b 312 br i1 %cmp1, label %end, label %taken 313 314taken: 315 %cmp2 = icmp ne i32 %a, %b 316 %or = or i1 %x, %cmp2 317 %c = select i1 %or, i32 20, i32 0 318 call void @foo(i32 %c) 319 br label %end 320 321end: 322 ret void 323} 324 325define void @implies_or_branch_comm(i32 %a, i32 %b, i1 %x) { 326; CHECK-LABEL: @implies_or_branch_comm( 327; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] 328; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 329; CHECK: taken: 330; CHECK-NEXT: call void @foo(i32 20) 331; CHECK-NEXT: br label [[END]] 332; CHECK: end: 333; CHECK-NEXT: ret void 334; 335 %cmp1 = icmp ne i32 %a, %b 336 br i1 %cmp1, label %taken, label %end 337 338taken: 339 %cmp2 = icmp ne i32 %a, %b 340 %or = or i1 %cmp2, %x 341 %c = select i1 %or, i32 20, i32 0 342 call void @foo(i32 %c) 343 br label %end 344 345end: 346 ret void 347} 348 349define void @implies_logical_or(i32 %a, i32 %b, i1 %x) { 350; CHECK-LABEL: @implies_logical_or( 351; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 352; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 353; CHECK: taken: 354; CHECK-NEXT: call void @foo(i32 20) 355; CHECK-NEXT: br label [[END]] 356; CHECK: end: 357; CHECK-NEXT: ret void 358; 359 %cmp1 = icmp eq i32 %a, %b 360 br i1 %cmp1, label %end, label %taken 361 362taken: 363 %cmp2 = icmp ne i32 %a, %b 364 %or = select i1 %cmp2, i1 true, i1 %x 365 %c = select i1 %or, i32 20, i32 0 366 call void @foo(i32 %c) 367 br label %end 368 369end: 370 ret void 371} 372 373define void @implies_logical_or_comm(i32 %a, i32 %b, i1 %x) { 374; CHECK-LABEL: @implies_logical_or_comm( 375; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 376; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 377; CHECK: taken: 378; CHECK-NEXT: call void @foo(i32 20) 379; CHECK-NEXT: br label [[END]] 380; CHECK: end: 381; CHECK-NEXT: ret void 382; 383 %cmp1 = icmp eq i32 %a, %b 384 br i1 %cmp1, label %end, label %taken 385 386taken: 387 %cmp2 = icmp ne i32 %a, %b 388 %or = select i1 %x, i1 true, i1 %cmp2 389 %c = select i1 %or, i32 20, i32 0 390 call void @foo(i32 %c) 391 br label %end 392 393end: 394 ret void 395} 396 397define void @doesnt_imply_and(i32 %a, i32 %b, i1 %x) { 398; CHECK-LABEL: @doesnt_imply_and( 399; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 400; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 401; CHECK: taken: 402; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]] 403; CHECK-NEXT: [[OR:%.*]] = and i1 [[CMP2]], [[X:%.*]] 404; CHECK-NEXT: [[C:%.*]] = select i1 [[OR]], i32 20, i32 0 405; CHECK-NEXT: call void @foo(i32 [[C]]) 406; CHECK-NEXT: br label [[END]] 407; CHECK: end: 408; CHECK-NEXT: ret void 409; 410 %cmp1 = icmp eq i32 %a, %b 411 br i1 %cmp1, label %end, label %taken 412 413taken: 414 %cmp2 = icmp ne i32 %a, %b 415 %or = and i1 %cmp2, %x 416 %c = select i1 %or, i32 20, i32 0 417 call void @foo(i32 %c) 418 br label %end 419 420end: 421 ret void 422} 423 424define void @implies_not_and(i32 %a, i32 %b, i1 %x) { 425; CHECK-LABEL: @implies_not_and( 426; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 427; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 428; CHECK: taken: 429; CHECK-NEXT: call void @foo(i32 0) 430; CHECK-NEXT: br label [[END]] 431; CHECK: end: 432; CHECK-NEXT: ret void 433; 434 %cmp1 = icmp eq i32 %a, %b 435 br i1 %cmp1, label %end, label %taken 436 437taken: 438 %cmp2 = icmp eq i32 %a, %b 439 %and = and i1 %cmp2, %x 440 %c = select i1 %and, i32 20, i32 0 441 call void @foo(i32 %c) 442 br label %end 443 444end: 445 ret void 446} 447 448define void @implies_not_and_comm(i32 %a, i32 %b, i1 %x) { 449; CHECK-LABEL: @implies_not_and_comm( 450; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 451; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 452; CHECK: taken: 453; CHECK-NEXT: call void @foo(i32 0) 454; CHECK-NEXT: br label [[END]] 455; CHECK: end: 456; CHECK-NEXT: ret void 457; 458 %cmp1 = icmp eq i32 %a, %b 459 br i1 %cmp1, label %end, label %taken 460 461taken: 462 %cmp2 = icmp eq i32 %a, %b 463 %and = and i1 %x, %cmp2 464 %c = select i1 %and, i32 20, i32 0 465 call void @foo(i32 %c) 466 br label %end 467 468end: 469 ret void 470} 471 472define void @implies_not_and_branch_comm(i32 %a, i32 %b, i1 %x) { 473; CHECK-LABEL: @implies_not_and_branch_comm( 474; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] 475; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 476; CHECK: taken: 477; CHECK-NEXT: call void @foo(i32 0) 478; CHECK-NEXT: br label [[END]] 479; CHECK: end: 480; CHECK-NEXT: ret void 481; 482 %cmp1 = icmp ne i32 %a, %b 483 br i1 %cmp1, label %taken, label %end 484 485taken: 486 %cmp2 = icmp eq i32 %a, %b 487 %and = and i1 %cmp2, %x 488 %c = select i1 %and, i32 20, i32 0 489 call void @foo(i32 %c) 490 br label %end 491 492end: 493 ret void 494} 495 496define void @implies_not_logical_and(i32 %a, i32 %b, i1 %x) { 497; CHECK-LABEL: @implies_not_logical_and( 498; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 499; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 500; CHECK: taken: 501; CHECK-NEXT: call void @foo(i32 0) 502; CHECK-NEXT: br label [[END]] 503; CHECK: end: 504; CHECK-NEXT: ret void 505; 506 %cmp1 = icmp eq i32 %a, %b 507 br i1 %cmp1, label %end, label %taken 508 509taken: 510 %cmp2 = icmp eq i32 %a, %b 511 %and = select i1 %cmp2, i1 %x, i1 false 512 %c = select i1 %and, i32 20, i32 0 513 call void @foo(i32 %c) 514 br label %end 515 516end: 517 ret void 518} 519 520define void @implies_not_logical_and_comm(i32 %a, i32 %b, i1 %x) { 521; CHECK-LABEL: @implies_not_logical_and_comm( 522; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 523; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 524; CHECK: taken: 525; CHECK-NEXT: call void @foo(i32 0) 526; CHECK-NEXT: br label [[END]] 527; CHECK: end: 528; CHECK-NEXT: ret void 529; 530 %cmp1 = icmp eq i32 %a, %b 531 br i1 %cmp1, label %end, label %taken 532 533taken: 534 %cmp2 = icmp eq i32 %a, %b 535 %and = select i1 %x, i1 %cmp2, i1 false 536 %c = select i1 %and, i32 20, i32 0 537 call void @foo(i32 %c) 538 br label %end 539 540end: 541 ret void 542} 543 544define void @doesnt_imply_or(i32 %a, i32 %b, i1 %x) { 545; CHECK-LABEL: @doesnt_imply_or( 546; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 547; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 548; CHECK: taken: 549; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]] 550; CHECK-NEXT: [[AND:%.*]] = or i1 [[CMP2]], [[X:%.*]] 551; CHECK-NEXT: [[C:%.*]] = select i1 [[AND]], i32 20, i32 0 552; CHECK-NEXT: call void @foo(i32 [[C]]) 553; CHECK-NEXT: br label [[END]] 554; CHECK: end: 555; CHECK-NEXT: ret void 556; 557 %cmp1 = icmp eq i32 %a, %b 558 br i1 %cmp1, label %end, label %taken 559 560taken: 561 %cmp2 = icmp eq i32 %a, %b 562 %and = or i1 %cmp2, %x 563 %c = select i1 %and, i32 20, i32 0 564 call void @foo(i32 %c) 565 br label %end 566 567end: 568 ret void 569} 570