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: br i1 false, label [[B0:%.*]], label [[B1]] 112; CHECK: b0: 113; CHECK-NEXT: call void @foo(i32 [[LEN]]) 114; CHECK-NEXT: br label [[B1]] 115; CHECK: b1: 116; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 117; CHECK-NEXT: br label [[RET:%.*]] 118; CHECK: ret: 119; CHECK-NEXT: call void @foo(i32 [[TMP1]]) 120; CHECK-NEXT: ret void 121; 122entry: 123 %0 = call i32 @bar(i32 %len); 124 %cmp = icmp ult i32 %len, 4 125 br i1 %cmp, label %bb, label %b1 126bb: 127 %cond = select i1 %cmp, i32 %len, i32 8 128 %cmp11 = icmp eq i32 %cond, 8 129 br i1 %cmp11, label %b0, label %b1 130 131b0: 132 call void @foo(i32 %len) 133 br label %b1 134 135b1: 136 %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] 137 br label %ret 138 139ret: 140 call void @foo(i32 %1) 141 ret void 142} 143 144; A >u 10 implies A >u 9 is true. 145 146define void @test5(i32 %a) { 147; CHECK-LABEL: @test5( 148; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10 149; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 150; CHECK: taken: 151; CHECK-NEXT: call void @foo(i32 30) 152; CHECK-NEXT: br label [[END]] 153; CHECK: end: 154; CHECK-NEXT: ret void 155; 156 %cmp1 = icmp ugt i32 %a, 10 157 br i1 %cmp1, label %taken, label %end 158 159taken: 160 %cmp2 = icmp ugt i32 %a, 9 161 %c = select i1 %cmp2, i32 30, i32 0 162 call void @foo(i32 %c) 163 br label %end 164 165end: 166 ret void 167} 168 169declare void @foo(i32) 170declare i32 @bar(i32) 171 172define i32 @test_and(i32 %a, i32 %b) { 173; CHECK-LABEL: @test_and( 174; CHECK-NEXT: entry: 175; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0 176; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0 177; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 178; CHECK-NEXT: br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]] 179; CHECK: tpath: 180; CHECK-NEXT: ret i32 313 181; CHECK: end: 182; CHECK-NEXT: ret i32 0 183; 184entry: 185 %cmp1 = icmp ne i32 %a, 0 186 %cmp2 = icmp ne i32 %b, 0 187 %and = and i1 %cmp1, %cmp2 188 br i1 %and, label %tpath, label %end 189 190tpath: 191 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false 192 %c = select i1 %cmp3, i32 0, i32 313 193 ret i32 %c 194 195end: 196 ret i32 0 197} 198 199; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true. 200 201define i32 @test_or1(i32 %a, i32 %b) { 202; CHECK-LABEL: @test_or1( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 205; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 206; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 207; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]] 208; CHECK: fpath: 209; CHECK-NEXT: ret i32 37 210; CHECK: end: 211; CHECK-NEXT: ret i32 0 212; 213entry: 214 %cmp1 = icmp eq i32 %a, 0 215 %cmp2 = icmp eq i32 %b, 0 216 %or = or i1 %cmp1, %cmp2 217 br i1 %or, label %end, label %fpath 218 219fpath: 220 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true 221 %c = select i1 %cmp3, i32 37, i32 0 222 ret i32 %c 223 224end: 225 ret i32 0 226} 227 228; LHS ==> RHS by definition (true -> true) 229 230define void @test6(i32 %a, i32 %b) { 231; CHECK-LABEL: @test6( 232; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 233; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 234; CHECK: taken: 235; CHECK-NEXT: call void @foo(i32 10) 236; CHECK-NEXT: br label [[END]] 237; CHECK: end: 238; CHECK-NEXT: ret void 239; 240 %cmp1 = icmp eq i32 %a, %b 241 br i1 %cmp1, label %taken, label %end 242 243taken: 244 %c = select i1 %cmp1, i32 10, i32 0 245 call void @foo(i32 %c) 246 br label %end 247 248end: 249 ret void 250} 251 252; LHS ==> RHS by definition (false -> false) 253 254define void @test7(i32 %a, i32 %b) { 255; CHECK-LABEL: @test7( 256; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 257; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 258; CHECK: taken: 259; CHECK-NEXT: call void @foo(i32 11) 260; CHECK-NEXT: br label [[END]] 261; CHECK: end: 262; CHECK-NEXT: ret void 263; 264 %cmp1 = icmp eq i32 %a, %b 265 br i1 %cmp1, label %end, label %taken 266 267taken: 268 %c = select i1 %cmp1, i32 0, i32 11 269 call void @foo(i32 %c) 270 br label %end 271 272end: 273 ret void 274} 275 276define void @implies_or(i32 %a, i32 %b, i1 %x) { 277; CHECK-LABEL: @implies_or( 278; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 279; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 280; CHECK: taken: 281; CHECK-NEXT: call void @foo(i32 20) 282; CHECK-NEXT: br label [[END]] 283; CHECK: end: 284; CHECK-NEXT: ret void 285; 286 %cmp1 = icmp eq i32 %a, %b 287 br i1 %cmp1, label %end, label %taken 288 289taken: 290 %cmp2 = icmp ne i32 %a, %b 291 %or = or i1 %cmp2, %x 292 %c = select i1 %or, i32 20, i32 0 293 call void @foo(i32 %c) 294 br label %end 295 296end: 297 ret void 298} 299 300define void @implies_or_comm(i32 %a, i32 %b, i1 %x) { 301; CHECK-LABEL: @implies_or_comm( 302; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 303; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 304; CHECK: taken: 305; CHECK-NEXT: call void @foo(i32 20) 306; CHECK-NEXT: br label [[END]] 307; CHECK: end: 308; CHECK-NEXT: ret void 309; 310 %cmp1 = icmp eq i32 %a, %b 311 br i1 %cmp1, label %end, label %taken 312 313taken: 314 %cmp2 = icmp ne i32 %a, %b 315 %or = or i1 %x, %cmp2 316 %c = select i1 %or, i32 20, i32 0 317 call void @foo(i32 %c) 318 br label %end 319 320end: 321 ret void 322} 323 324define void @implies_or_branch_comm(i32 %a, i32 %b, i1 %x) { 325; CHECK-LABEL: @implies_or_branch_comm( 326; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] 327; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 328; CHECK: taken: 329; CHECK-NEXT: call void @foo(i32 20) 330; CHECK-NEXT: br label [[END]] 331; CHECK: end: 332; CHECK-NEXT: ret void 333; 334 %cmp1 = icmp ne i32 %a, %b 335 br i1 %cmp1, label %taken, label %end 336 337taken: 338 %cmp2 = icmp ne i32 %a, %b 339 %or = or i1 %cmp2, %x 340 %c = select i1 %or, i32 20, i32 0 341 call void @foo(i32 %c) 342 br label %end 343 344end: 345 ret void 346} 347 348define void @implies_logical_or(i32 %a, i32 %b, i1 %x) { 349; CHECK-LABEL: @implies_logical_or( 350; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 351; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 352; CHECK: taken: 353; CHECK-NEXT: call void @foo(i32 20) 354; CHECK-NEXT: br label [[END]] 355; CHECK: end: 356; CHECK-NEXT: ret void 357; 358 %cmp1 = icmp eq i32 %a, %b 359 br i1 %cmp1, label %end, label %taken 360 361taken: 362 %cmp2 = icmp ne i32 %a, %b 363 %or = select i1 %cmp2, i1 true, i1 %x 364 %c = select i1 %or, i32 20, i32 0 365 call void @foo(i32 %c) 366 br label %end 367 368end: 369 ret void 370} 371 372define void @implies_logical_or_comm(i32 %a, i32 %b, i1 %x) { 373; CHECK-LABEL: @implies_logical_or_comm( 374; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 375; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 376; CHECK: taken: 377; CHECK-NEXT: call void @foo(i32 20) 378; CHECK-NEXT: br label [[END]] 379; CHECK: end: 380; CHECK-NEXT: ret void 381; 382 %cmp1 = icmp eq i32 %a, %b 383 br i1 %cmp1, label %end, label %taken 384 385taken: 386 %cmp2 = icmp ne i32 %a, %b 387 %or = select i1 %x, i1 true, i1 %cmp2 388 %c = select i1 %or, i32 20, i32 0 389 call void @foo(i32 %c) 390 br label %end 391 392end: 393 ret void 394} 395 396define void @doesnt_imply_and(i32 %a, i32 %b, i1 %x) { 397; CHECK-LABEL: @doesnt_imply_and( 398; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 399; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 400; CHECK: taken: 401; CHECK-NEXT: [[C:%.*]] = select i1 [[X:%.*]], i32 20, i32 0 402; CHECK-NEXT: call void @foo(i32 [[C]]) 403; CHECK-NEXT: br label [[END]] 404; CHECK: end: 405; CHECK-NEXT: ret void 406; 407 %cmp1 = icmp eq i32 %a, %b 408 br i1 %cmp1, label %end, label %taken 409 410taken: 411 %cmp2 = icmp ne i32 %a, %b 412 %or = and i1 %cmp2, %x 413 %c = select i1 %or, i32 20, i32 0 414 call void @foo(i32 %c) 415 br label %end 416 417end: 418 ret void 419} 420 421define void @implies_not_and(i32 %a, i32 %b, i1 %x) { 422; CHECK-LABEL: @implies_not_and( 423; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 424; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 425; CHECK: taken: 426; CHECK-NEXT: call void @foo(i32 0) 427; CHECK-NEXT: br label [[END]] 428; CHECK: end: 429; CHECK-NEXT: ret void 430; 431 %cmp1 = icmp eq i32 %a, %b 432 br i1 %cmp1, label %end, label %taken 433 434taken: 435 %cmp2 = icmp eq i32 %a, %b 436 %and = and i1 %cmp2, %x 437 %c = select i1 %and, i32 20, i32 0 438 call void @foo(i32 %c) 439 br label %end 440 441end: 442 ret void 443} 444 445define void @implies_not_and_comm(i32 %a, i32 %b, i1 %x) { 446; CHECK-LABEL: @implies_not_and_comm( 447; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 448; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 449; CHECK: taken: 450; CHECK-NEXT: call void @foo(i32 0) 451; CHECK-NEXT: br label [[END]] 452; CHECK: end: 453; CHECK-NEXT: ret void 454; 455 %cmp1 = icmp eq i32 %a, %b 456 br i1 %cmp1, label %end, label %taken 457 458taken: 459 %cmp2 = icmp eq i32 %a, %b 460 %and = and i1 %x, %cmp2 461 %c = select i1 %and, i32 20, i32 0 462 call void @foo(i32 %c) 463 br label %end 464 465end: 466 ret void 467} 468 469define void @implies_not_and_branch_comm(i32 %a, i32 %b, i1 %x) { 470; CHECK-LABEL: @implies_not_and_branch_comm( 471; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] 472; CHECK-NEXT: br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]] 473; CHECK: taken: 474; CHECK-NEXT: call void @foo(i32 0) 475; CHECK-NEXT: br label [[END]] 476; CHECK: end: 477; CHECK-NEXT: ret void 478; 479 %cmp1 = icmp ne i32 %a, %b 480 br i1 %cmp1, label %taken, label %end 481 482taken: 483 %cmp2 = icmp eq i32 %a, %b 484 %and = and i1 %cmp2, %x 485 %c = select i1 %and, i32 20, i32 0 486 call void @foo(i32 %c) 487 br label %end 488 489end: 490 ret void 491} 492 493define void @implies_not_logical_and(i32 %a, i32 %b, i1 %x) { 494; CHECK-LABEL: @implies_not_logical_and( 495; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 496; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 497; CHECK: taken: 498; CHECK-NEXT: call void @foo(i32 0) 499; CHECK-NEXT: br label [[END]] 500; CHECK: end: 501; CHECK-NEXT: ret void 502; 503 %cmp1 = icmp eq i32 %a, %b 504 br i1 %cmp1, label %end, label %taken 505 506taken: 507 %cmp2 = icmp eq i32 %a, %b 508 %and = select i1 %cmp2, i1 %x, i1 false 509 %c = select i1 %and, i32 20, i32 0 510 call void @foo(i32 %c) 511 br label %end 512 513end: 514 ret void 515} 516 517define void @implies_not_logical_and_comm(i32 %a, i32 %b, i1 %x) { 518; CHECK-LABEL: @implies_not_logical_and_comm( 519; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 520; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 521; CHECK: taken: 522; CHECK-NEXT: call void @foo(i32 0) 523; CHECK-NEXT: br label [[END]] 524; CHECK: end: 525; CHECK-NEXT: ret void 526; 527 %cmp1 = icmp eq i32 %a, %b 528 br i1 %cmp1, label %end, label %taken 529 530taken: 531 %cmp2 = icmp eq i32 %a, %b 532 %and = select i1 %x, i1 %cmp2, i1 false 533 %c = select i1 %and, i32 20, i32 0 534 call void @foo(i32 %c) 535 br label %end 536 537end: 538 ret void 539} 540 541define void @doesnt_imply_or(i32 %a, i32 %b, i1 %x) { 542; CHECK-LABEL: @doesnt_imply_or( 543; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 544; CHECK-NEXT: br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]] 545; CHECK: taken: 546; CHECK-NEXT: [[C:%.*]] = select i1 [[X:%.*]], i32 20, i32 0 547; CHECK-NEXT: call void @foo(i32 [[C]]) 548; CHECK-NEXT: br label [[END]] 549; CHECK: end: 550; CHECK-NEXT: ret void 551; 552 %cmp1 = icmp eq i32 %a, %b 553 br i1 %cmp1, label %end, label %taken 554 555taken: 556 %cmp2 = icmp eq i32 %a, %b 557 %and = or i1 %cmp2, %x 558 %c = select i1 %and, i32 20, i32 0 559 call void @foo(i32 %c) 560 br label %end 561 562end: 563 ret void 564} 565