1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=gvn -S | FileCheck %s 3 4@a = external global i32 ; <ptr> [#uses=7] 5 6define i32 @test1() nounwind { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 10; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4 11; CHECK-NEXT: br i1 [[TMP1]], label [[BB:%.*]], label [[BB1:%.*]] 12; CHECK: bb: 13; CHECK-NEXT: br label [[BB8:%.*]] 14; CHECK: bb1: 15; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 5 16; CHECK-NEXT: br i1 [[TMP2]], label [[BB2:%.*]], label [[BB3:%.*]] 17; CHECK: bb2: 18; CHECK-NEXT: br label [[BB8]] 19; CHECK: bb3: 20; CHECK-NEXT: br i1 false, label [[BB4:%.*]], label [[BB5:%.*]] 21; CHECK: bb4: 22; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @a, align 4 23; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 5 24; CHECK-NEXT: br label [[BB8]] 25; CHECK: bb5: 26; CHECK-NEXT: br i1 false, label [[BB6:%.*]], label [[BB7:%.*]] 27; CHECK: bb6: 28; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr @a, align 4 29; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 4 30; CHECK-NEXT: br label [[BB8]] 31; CHECK: bb7: 32; CHECK-NEXT: br label [[BB8]] 33; CHECK: bb8: 34; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP0]], [[BB7]] ], [ poison, [[BB6]] ], [ poison, [[BB4]] ], [ 4, [[BB2]] ], [ 5, [[BB]] ] 35; CHECK-NEXT: ret i32 [[DOT0]] 36; 37entry: 38 %0 = load i32, ptr @a, align 4 39 %1 = icmp eq i32 %0, 4 40 br i1 %1, label %bb, label %bb1 41 42bb: ; preds = %entry 43 br label %bb8 44 45bb1: ; preds = %entry 46 %2 = load i32, ptr @a, align 4 47 %3 = icmp eq i32 %2, 5 48 br i1 %3, label %bb2, label %bb3 49 50bb2: ; preds = %bb1 51 br label %bb8 52 53bb3: ; preds = %bb1 54 %4 = load i32, ptr @a, align 4 55 %5 = icmp eq i32 %4, 4 56 br i1 %5, label %bb4, label %bb5 57 58bb4: ; preds = %bb3 59 %6 = load i32, ptr @a, align 4 60 %7 = add i32 %6, 5 61 br label %bb8 62 63bb5: ; preds = %bb3 64 %8 = load i32, ptr @a, align 4 65 %9 = icmp eq i32 %8, 5 66 br i1 %9, label %bb6, label %bb7 67 68bb6: ; preds = %bb5 69 %10 = load i32, ptr @a, align 4 70 %11 = add i32 %10, 4 71 br label %bb8 72 73bb7: ; preds = %bb5 74 %12 = load i32, ptr @a, align 4 75 br label %bb8 76 77bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb 78 %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ] 79 br label %return 80 81return: ; preds = %bb8 82 ret i32 %.0 83} 84 85declare void @foo(i1) 86declare void @bar(i32) 87 88define void @test3(i32 %x, i32 %y) { 89; CHECK-LABEL: @test3( 90; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 91; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 92; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] 93; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]] 94; CHECK: both_zero: 95; CHECK-NEXT: call void @foo(i1 true) 96; CHECK-NEXT: call void @foo(i1 true) 97; CHECK-NEXT: call void @bar(i32 0) 98; CHECK-NEXT: call void @bar(i32 0) 99; CHECK-NEXT: ret void 100; CHECK: nope: 101; CHECK-NEXT: call void @foo(i1 false) 102; CHECK-NEXT: ret void 103; 104 %xz = icmp eq i32 %x, 0 105 %yz = icmp eq i32 %y, 0 106 %z = and i1 %xz, %yz 107 br i1 %z, label %both_zero, label %nope 108both_zero: 109 call void @foo(i1 %xz) 110 call void @foo(i1 %yz) 111 call void @bar(i32 %x) 112 call void @bar(i32 %y) 113 ret void 114nope: 115 call void @foo(i1 %z) 116 ret void 117} 118 119define void @test3_select(i32 %x, i32 %y) { 120; CHECK-LABEL: @test3_select( 121; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 122; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 123; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false 124; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]] 125; CHECK: both_zero: 126; CHECK-NEXT: call void @foo(i1 true) 127; CHECK-NEXT: call void @foo(i1 true) 128; CHECK-NEXT: call void @bar(i32 0) 129; CHECK-NEXT: call void @bar(i32 0) 130; CHECK-NEXT: ret void 131; CHECK: nope: 132; CHECK-NEXT: call void @foo(i1 false) 133; CHECK-NEXT: ret void 134; 135 %xz = icmp eq i32 %x, 0 136 %yz = icmp eq i32 %y, 0 137 %z = select i1 %xz, i1 %yz, i1 false 138 br i1 %z, label %both_zero, label %nope 139both_zero: 140 call void @foo(i1 %xz) 141 call void @foo(i1 %yz) 142 call void @bar(i32 %x) 143 call void @bar(i32 %y) 144 ret void 145nope: 146 call void @foo(i1 %z) 147 ret void 148} 149 150define void @test3_or(i32 %x, i32 %y) { 151; CHECK-LABEL: @test3_or( 152; CHECK-NEXT: [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0 153; CHECK-NEXT: [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 154; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] 155; CHECK-NEXT: br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]] 156; CHECK: both_zero: 157; CHECK-NEXT: call void @foo(i1 false) 158; CHECK-NEXT: call void @foo(i1 false) 159; CHECK-NEXT: call void @bar(i32 0) 160; CHECK-NEXT: call void @bar(i32 0) 161; CHECK-NEXT: ret void 162; CHECK: nope: 163; CHECK-NEXT: call void @foo(i1 true) 164; CHECK-NEXT: ret void 165; 166 %xz = icmp ne i32 %x, 0 167 %yz = icmp ne i32 %y, 0 168 %z = or i1 %xz, %yz 169 br i1 %z, label %nope, label %both_zero 170both_zero: 171 call void @foo(i1 %xz) 172 call void @foo(i1 %yz) 173 call void @bar(i32 %x) 174 call void @bar(i32 %y) 175 ret void 176nope: 177 call void @foo(i1 %z) 178 ret void 179} 180 181define void @test3_or_select(i32 %x, i32 %y) { 182; CHECK-LABEL: @test3_or_select( 183; CHECK-NEXT: [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0 184; CHECK-NEXT: [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 185; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]] 186; CHECK-NEXT: br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]] 187; CHECK: both_zero: 188; CHECK-NEXT: call void @foo(i1 false) 189; CHECK-NEXT: call void @foo(i1 false) 190; CHECK-NEXT: call void @bar(i32 0) 191; CHECK-NEXT: call void @bar(i32 0) 192; CHECK-NEXT: ret void 193; CHECK: nope: 194; CHECK-NEXT: call void @foo(i1 true) 195; CHECK-NEXT: ret void 196; 197 %xz = icmp ne i32 %x, 0 198 %yz = icmp ne i32 %y, 0 199 %z = select i1 %xz, i1 true, i1 %yz 200 br i1 %z, label %nope, label %both_zero 201both_zero: 202 call void @foo(i1 %xz) 203 call void @foo(i1 %yz) 204 call void @bar(i32 %x) 205 call void @bar(i32 %y) 206 ret void 207nope: 208 call void @foo(i1 %z) 209 ret void 210} 211 212define void @test4(i1 %b, i32 %x) { 213; CHECK-LABEL: @test4( 214; CHECK-NEXT: br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]] 215; CHECK: sw: 216; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [ 217; CHECK-NEXT: i32 0, label [[CASE0:%.*]] 218; CHECK-NEXT: i32 1, label [[CASE1:%.*]] 219; CHECK-NEXT: i32 2, label [[CASE0]] 220; CHECK-NEXT: i32 3, label [[CASE3]] 221; CHECK-NEXT: i32 4, label [[DEFAULT]] 222; CHECK-NEXT: ] 223; CHECK: default: 224; CHECK-NEXT: call void @bar(i32 [[X]]) 225; CHECK-NEXT: ret void 226; CHECK: case0: 227; CHECK-NEXT: call void @bar(i32 [[X]]) 228; CHECK-NEXT: ret void 229; CHECK: case1: 230; CHECK-NEXT: call void @bar(i32 1) 231; CHECK-NEXT: ret void 232; CHECK: case3: 233; CHECK-NEXT: call void @bar(i32 [[X]]) 234; CHECK-NEXT: ret void 235; 236 br i1 %b, label %sw, label %case3 237sw: 238 switch i32 %x, label %default [ 239 i32 0, label %case0 240 i32 1, label %case1 241 i32 2, label %case0 242 i32 3, label %case3 243 i32 4, label %default 244 ] 245default: 246 call void @bar(i32 %x) 247 ret void 248case0: 249 call void @bar(i32 %x) 250 ret void 251case1: 252 call void @bar(i32 %x) 253 ret void 254case3: 255 call void @bar(i32 %x) 256 ret void 257} 258 259define i1 @test5(i32 %x, i32 %y) { 260; CHECK-LABEL: @test5( 261; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] 262; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 263; CHECK: same: 264; CHECK-NEXT: ret i1 false 265; CHECK: different: 266; CHECK-NEXT: ret i1 false 267; 268 %cmp = icmp eq i32 %x, %y 269 br i1 %cmp, label %same, label %different 270 271same: 272 %cmp2 = icmp ne i32 %x, %y 273 ret i1 %cmp2 274 275different: 276 %cmp3 = icmp eq i32 %x, %y 277 ret i1 %cmp3 278} 279 280define i1 @test6(i32 %x, i32 %y) { 281; CHECK-LABEL: @test6( 282; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] 283; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]] 284; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 285; CHECK: same: 286; CHECK-NEXT: ret i1 false 287; CHECK: different: 288; CHECK-NEXT: ret i1 false 289; 290 %cmp2 = icmp ne i32 %x, %y 291 %cmp = icmp eq i32 %x, %y 292 %cmp3 = icmp eq i32 %x, %y 293 br i1 %cmp, label %same, label %different 294 295same: 296 ret i1 %cmp2 297 298different: 299 ret i1 %cmp3 300} 301 302define i1 @test6_fp(float %x, float %y) { 303; CHECK-LABEL: @test6_fp( 304; CHECK-NEXT: [[CMP2:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]] 305; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X]], [[Y]] 306; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 307; CHECK: same: 308; CHECK-NEXT: ret i1 false 309; CHECK: different: 310; CHECK-NEXT: ret i1 false 311; 312 %cmp2 = fcmp une float %x, %y 313 %cmp = fcmp oeq float %x, %y 314 %cmp3 = fcmp oeq float %x, %y 315 br i1 %cmp, label %same, label %different 316 317same: 318 ret i1 %cmp2 319 320different: 321 ret i1 %cmp3 322} 323 324define i1 @test7(i32 %x, i32 %y) { 325; CHECK-LABEL: @test7( 326; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]] 327; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 328; CHECK: same: 329; CHECK-NEXT: ret i1 false 330; CHECK: different: 331; CHECK-NEXT: ret i1 false 332; 333 %cmp = icmp sgt i32 %x, %y 334 br i1 %cmp, label %same, label %different 335 336same: 337 %cmp2 = icmp sle i32 %x, %y 338 ret i1 %cmp2 339 340different: 341 %cmp3 = icmp sgt i32 %x, %y 342 ret i1 %cmp3 343} 344 345define i1 @test7_fp(float %x, float %y) { 346; CHECK-LABEL: @test7_fp( 347; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] 348; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 349; CHECK: same: 350; CHECK-NEXT: ret i1 false 351; CHECK: different: 352; CHECK-NEXT: ret i1 false 353; 354 %cmp = fcmp ogt float %x, %y 355 br i1 %cmp, label %same, label %different 356 357same: 358 %cmp2 = fcmp ule float %x, %y 359 ret i1 %cmp2 360 361different: 362 %cmp3 = fcmp ogt float %x, %y 363 ret i1 %cmp3 364} 365 366define i1 @test8(i32 %x, i32 %y) { 367; CHECK-LABEL: @test8( 368; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]] 369; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]] 370; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 371; CHECK: same: 372; CHECK-NEXT: ret i1 false 373; CHECK: different: 374; CHECK-NEXT: ret i1 false 375; 376 %cmp2 = icmp sle i32 %x, %y 377 %cmp = icmp sgt i32 %x, %y 378 %cmp3 = icmp sgt i32 %x, %y 379 br i1 %cmp, label %same, label %different 380 381same: 382 ret i1 %cmp2 383 384different: 385 ret i1 %cmp3 386} 387 388define i1 @test8_fp(float %x, float %y) { 389; CHECK-LABEL: @test8_fp( 390; CHECK-NEXT: [[CMP2:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]] 391; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X]], [[Y]] 392; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]] 393; CHECK: same: 394; CHECK-NEXT: ret i1 false 395; CHECK: different: 396; CHECK-NEXT: ret i1 false 397; 398 %cmp2 = fcmp ule float %x, %y 399 %cmp = fcmp ogt float %x, %y 400 %cmp3 = fcmp ogt float %x, %y 401 br i1 %cmp, label %same, label %different 402 403same: 404 ret i1 %cmp2 405 406different: 407 ret i1 %cmp3 408} 409 410; PR1768 411define i32 @test9(i32 %i, i32 %j) { 412; CHECK-LABEL: @test9( 413; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]] 414; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]] 415; CHECK: cond_true: 416; CHECK-NEXT: ret i32 0 417; CHECK: ret: 418; CHECK-NEXT: ret i32 5 419; 420 %cmp = icmp eq i32 %i, %j 421 br i1 %cmp, label %cond_true, label %ret 422 423cond_true: 424 %diff = sub i32 %i, %j 425 ret i32 %diff 426 427ret: 428 ret i32 5 429} 430 431; PR1768 432define i32 @test10(i32 %j, i32 %i) { 433; CHECK-LABEL: @test10( 434; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]] 435; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]] 436; CHECK: cond_true: 437; CHECK-NEXT: ret i32 0 438; CHECK: ret: 439; CHECK-NEXT: ret i32 5 440; 441 %cmp = icmp eq i32 %i, %j 442 br i1 %cmp, label %cond_true, label %ret 443 444cond_true: 445 %diff = sub i32 %i, %j 446 ret i32 %diff 447 448ret: 449 ret i32 5 450} 451 452declare i32 @yogibar() 453 454define i32 @test11(i32 %x) { 455; CHECK-LABEL: @test11( 456; CHECK-NEXT: [[V0:%.*]] = call i32 @yogibar() 457; CHECK-NEXT: [[V1:%.*]] = call i32 @yogibar() 458; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]] 459; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]] 460; CHECK: cond_true: 461; CHECK-NEXT: ret i32 [[V0]] 462; CHECK: next: 463; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0]] 464; CHECK-NEXT: br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]] 465; CHECK: cond_true2: 466; CHECK-NEXT: ret i32 [[X]] 467; CHECK: next2: 468; CHECK-NEXT: ret i32 0 469; 470 %v0 = call i32 @yogibar() 471 %v1 = call i32 @yogibar() 472 %cmp = icmp eq i32 %v0, %v1 473 br i1 %cmp, label %cond_true, label %next 474 475cond_true: 476 ret i32 %v1 477 478next: 479 %cmp2 = icmp eq i32 %x, %v0 480 br i1 %cmp2, label %cond_true2, label %next2 481 482cond_true2: 483 ret i32 %v0 484 485next2: 486 ret i32 0 487} 488 489define i32 @test12(i32 %x) { 490; CHECK-LABEL: @test12( 491; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0 492; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 493; CHECK: cond_true: 494; CHECK-NEXT: br label [[RET:%.*]] 495; CHECK: cond_false: 496; CHECK-NEXT: br label [[RET]] 497; CHECK: ret: 498; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ [[X]], [[COND_FALSE]] ] 499; CHECK-NEXT: ret i32 [[RES]] 500; 501 %cmp = icmp eq i32 %x, 0 502 br i1 %cmp, label %cond_true, label %cond_false 503 504cond_true: 505 br label %ret 506 507cond_false: 508 br label %ret 509 510ret: 511 %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ] 512 ret i32 %res 513} 514 515; On the path from entry->if->end we know that ptr1==ptr2, so we can determine 516; that gep2 does not alias ptr1 on that path (as it would require that 517; ptr2==ptr2+2), so we can perform PRE of the load. 518define i32 @test13(ptr %ptr1, ptr %ptr2) { 519; CHECK-LABEL: @test13( 520; CHECK-NEXT: entry: 521; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[PTR2:%.*]], i32 1 522; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[PTR2]], i32 2 523; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[PTR1:%.*]], [[PTR2]] 524; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 525; CHECK: if: 526; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[GEP2]], align 4 527; CHECK-NEXT: br label [[END]] 528; CHECK: end: 529; CHECK-NEXT: [[PHI1:%.*]] = phi ptr [ [[PTR1]], [[IF]] ], [ [[GEP1]], [[ENTRY:%.*]] ] 530; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[VAL1]], [[IF]] ], [ 0, [[ENTRY]] ] 531; CHECK-NEXT: store i32 0, ptr [[PHI1]], align 4 532; CHECK-NEXT: [[VAL2:%.*]] = load i32, ptr [[GEP2]], align 4 533; CHECK-NEXT: [[RET:%.*]] = add i32 [[PHI2]], [[VAL2]] 534; CHECK-NEXT: ret i32 [[RET]] 535; 536entry: 537 %gep1 = getelementptr i32, ptr %ptr2, i32 1 538 %gep2 = getelementptr i32, ptr %ptr2, i32 2 539 %cmp = icmp eq ptr %ptr1, %ptr2 540 br i1 %cmp, label %if, label %end 541 542 543if: 544 %val1 = load i32, ptr %gep2, align 4 545 br label %end 546 547end: 548 %phi1 = phi ptr [ %ptr1, %if ], [ %gep1, %entry ] 549 %phi2 = phi i32 [ %val1, %if ], [ 0, %entry ] 550 store i32 0, ptr %phi1, align 4 551 %val2 = load i32, ptr %gep2, align 4 552 %ret = add i32 %phi2, %val2 553 ret i32 %ret 554} 555 556define void @test14(ptr %ptr1, ptr noalias %ptr2, i1 %b1, i1 %b2) { 557; CHECK-LABEL: @test14( 558; CHECK-NEXT: entry: 559; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[PTR1:%.*]], i32 1 560; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[PTR1]], i32 2 561; CHECK-NEXT: br label [[LOOP:%.*]] 562; CHECK: loop: 563; CHECK-NEXT: br i1 [[B1:%.*]], label [[LOOP_IF1_CRIT_EDGE:%.*]], label [[THEN:%.*]] 564; CHECK: loop.if1_crit_edge: 565; CHECK-NEXT: [[VAL2_PRE:%.*]] = load i32, ptr [[GEP2]], align 4 566; CHECK-NEXT: br label [[IF1:%.*]] 567; CHECK: if1: 568; CHECK-NEXT: [[VAL2:%.*]] = phi i32 [ [[VAL2_PRE]], [[LOOP_IF1_CRIT_EDGE]] ], [ [[VAL3:%.*]], [[LOOP_END:%.*]] ] 569; CHECK-NEXT: store i32 [[VAL2]], ptr [[GEP2]], align 4 570; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4 571; CHECK-NEXT: br label [[THEN]] 572; CHECK: then: 573; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[PTR2:%.*]] 574; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_END]], label [[IF2:%.*]] 575; CHECK: if2: 576; CHECK-NEXT: br label [[LOOP_END]] 577; CHECK: loop.end: 578; CHECK-NEXT: [[PHI3:%.*]] = phi ptr [ [[GEP2]], [[THEN]] ], [ [[PTR1]], [[IF2]] ] 579; CHECK-NEXT: [[VAL3]] = load i32, ptr [[GEP2]], align 4 580; CHECK-NEXT: store i32 [[VAL3]], ptr [[PHI3]], align 4 581; CHECK-NEXT: br i1 [[B2:%.*]], label [[LOOP]], label [[IF1]] 582; 583entry: 584 %gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1 585 %gep2 = getelementptr inbounds i32, ptr %ptr1, i32 2 586 br label %loop 587 588loop: 589 %phi1 = phi ptr [ %gep3, %loop.end ], [ %gep1, %entry ] 590 br i1 %b1, label %if1, label %then 591 592 593if1: 594 %val2 = load i32, ptr %gep2, align 4 595 store i32 %val2, ptr %gep2, align 4 596 store i32 0, ptr %phi1, align 4 597 br label %then 598 599then: 600 %cmp = icmp eq ptr %gep2, %ptr2 601 br i1 %cmp, label %loop.end, label %if2 602 603if2: 604 br label %loop.end 605 606loop.end: 607 %phi3 = phi ptr [ %gep2, %then ], [ %ptr1, %if2 ] 608 %val3 = load i32, ptr %gep2, align 4 609 store i32 %val3, ptr %phi3, align 4 610 %gep3 = getelementptr inbounds i32, ptr %ptr1, i32 1 611 br i1 %b2, label %loop, label %if1 612} 613 614; Make sure that the call to use_ptr does not have %p1 615define void @single_phi1(ptr %p0, ptr %p1, i8 %s) { 616; CHECK-LABEL: @single_phi1( 617; CHECK-NEXT: entry: 618; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8 619; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] 620; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] 621; CHECK: bb1: 622; CHECK-NEXT: switch i8 [[S:%.*]], label [[BB2:%.*]] [ 623; CHECK-NEXT: i8 0, label [[BB1]] 624; CHECK-NEXT: i8 1, label [[BB3:%.*]] 625; CHECK-NEXT: ] 626; CHECK: bb2: 627; CHECK-NEXT: unreachable 628; CHECK: bb3: 629; CHECK-NEXT: br label [[BB4]] 630; CHECK: bb4: 631; CHECK-NEXT: call void @use_bool(i1 [[CMP1]]) 632; CHECK-NEXT: call void @use_ptr(ptr [[P2]]) 633; CHECK-NEXT: ret void 634; 635entry: 636 %p2 = load ptr, ptr %p0, align 8 637 %cmp1 = icmp eq ptr %p2, %p1 638 br i1 %cmp1, label %bb4, label %bb1 639 640bb1: 641 switch i8 %s, label %bb2 [ 642 i8 0, label %bb1 643 i8 1, label %bb3 644 ] 645 646bb2: 647 unreachable 648 649bb3: 650 br label %bb4 651 652bb4: 653 %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb3 ] 654 %cmp2 = icmp eq ptr %phi1, %p1 655 call void @use_bool(i1 %cmp2) 656 call void @use_ptr(ptr %phi1) 657 ret void 658} 659 660define void @single_phi2(ptr %p0, ptr %p1, i8 %s) { 661; CHECK-LABEL: @single_phi2( 662; CHECK-NEXT: entry: 663; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8 664; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] 665; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] 666; CHECK: bb1: 667; CHECK-NEXT: switch i8 [[S:%.*]], label [[BB2:%.*]] [ 668; CHECK-NEXT: i8 0, label [[BB1]] 669; CHECK-NEXT: i8 1, label [[BB3:%.*]] 670; CHECK-NEXT: ] 671; CHECK: bb2: 672; CHECK-NEXT: br label [[BB4]] 673; CHECK: bb3: 674; CHECK-NEXT: br label [[BB4]] 675; CHECK: bb4: 676; CHECK-NEXT: call void @use_bool(i1 [[CMP1]]) 677; CHECK-NEXT: call void @use_ptr(ptr [[P2]]) 678; CHECK-NEXT: ret void 679; 680entry: 681 %p2 = load ptr, ptr %p0, align 8 682 %cmp1 = icmp eq ptr %p2, %p1 683 br i1 %cmp1, label %bb4, label %bb1 684 685bb1: 686 switch i8 %s, label %bb2 [ 687 i8 0, label %bb1 688 i8 1, label %bb3 689 ] 690 691bb2: 692 br label %bb4 693 694bb3: 695 br label %bb4 696 697bb4: 698 %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ %p2, %bb3 ] 699 %cmp2 = icmp eq ptr %phi1, %p1 700 call void @use_bool(i1 %cmp2) 701 call void @use_ptr(ptr %phi1) 702 ret void 703} 704 705define void @multiple_phi1(ptr %p0, ptr %p1, i8 %s) { 706; CHECK-LABEL: @multiple_phi1( 707; CHECK-NEXT: entry: 708; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8 709; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] 710; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] 711; CHECK: bb1: 712; CHECK-NEXT: switch i8 [[S:%.*]], label [[BB2:%.*]] [ 713; CHECK-NEXT: i8 0, label [[BB1]] 714; CHECK-NEXT: i8 1, label [[BB3:%.*]] 715; CHECK-NEXT: ] 716; CHECK: bb2: 717; CHECK-NEXT: unreachable 718; CHECK: bb3: 719; CHECK-NEXT: br label [[BB4]] 720; CHECK: bb4: 721; CHECK-NEXT: call void @use_bool(i1 [[CMP1]]) 722; CHECK-NEXT: br label [[BB5:%.*]] 723; CHECK: bb5: 724; CHECK-NEXT: call void @use_ptr(ptr [[P2]]) 725; CHECK-NEXT: br label [[BB5]] 726; 727entry: 728 %p2 = load ptr, ptr %p0, align 8 729 %cmp1 = icmp eq ptr %p2, %p1 730 br i1 %cmp1, label %bb4, label %bb1 731 732bb1: 733 switch i8 %s, label %bb2 [ 734 i8 0, label %bb1 735 i8 1, label %bb3 736 ] 737 738bb2: 739 unreachable 740 741bb3: 742 br label %bb4 743 744bb4: 745 %phi1 = phi ptr [ %p2, %entry ], [ poison, %bb3 ] 746 %cmp2 = icmp eq ptr %phi1, %p1 747 call void @use_bool(i1 %cmp2) 748 br label %bb5 749 750bb5: 751 %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ] 752 call void @use_ptr(ptr %phi2) 753 br label %bb5 754} 755 756define void @multiple_phi2(ptr %p0, ptr %p1, i8 %s) { 757; CHECK-LABEL: @multiple_phi2( 758; CHECK-NEXT: entry: 759; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8 760; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] 761; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] 762; CHECK: bb1: 763; CHECK-NEXT: switch i8 [[S:%.*]], label [[BB2:%.*]] [ 764; CHECK-NEXT: i8 0, label [[BB1]] 765; CHECK-NEXT: i8 1, label [[BB3:%.*]] 766; CHECK-NEXT: ] 767; CHECK: bb2: 768; CHECK-NEXT: br label [[BB4]] 769; CHECK: bb3: 770; CHECK-NEXT: br label [[BB4]] 771; CHECK: bb4: 772; CHECK-NEXT: call void @use_bool(i1 [[CMP1]]) 773; CHECK-NEXT: br label [[BB5:%.*]] 774; CHECK: bb5: 775; CHECK-NEXT: call void @use_ptr(ptr [[P2]]) 776; CHECK-NEXT: br label [[BB5]] 777; 778entry: 779 %p2 = load ptr, ptr %p0, align 8 780 %cmp1 = icmp eq ptr %p2, %p1 781 br i1 %cmp1, label %bb4, label %bb1 782 783bb1: 784 switch i8 %s, label %bb2 [ 785 i8 0, label %bb1 786 i8 1, label %bb3 787 ] 788 789bb2: 790 br label %bb4 791 792bb3: 793 br label %bb4 794 795bb4: 796 %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ poison, %bb3 ] 797 %cmp2 = icmp eq ptr %phi1, %p1 798 call void @use_bool(i1 %cmp2) 799 br label %bb5 800 801bb5: 802 %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ] 803 call void @use_ptr(ptr %phi2) 804 br label %bb5 805} 806 807define void @select_same_obj(i1 %c, ptr %p, i64 %x) { 808; CHECK-LABEL: @select_same_obj( 809; CHECK-NEXT: entry: 810; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X:%.*]] 811; CHECK-NEXT: [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P]], ptr [[P2]] 812; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]] 813; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]] 814; CHECK: if: 815; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 816; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 817; CHECK-NEXT: ret void 818; CHECK: exit: 819; CHECK-NEXT: ret void 820; 821entry: 822 %p2 = getelementptr i8, ptr %p, i64 %x 823 %p3 = select i1 %c, ptr %p, ptr %p2 824 %cmp = icmp eq ptr %p, %p3 825 br i1 %cmp, label %if, label %exit 826 827if: 828 call void @use_ptr(ptr %p) 829 call void @use_ptr(ptr %p3) 830 ret void 831 832exit: 833 ret void 834} 835 836define void @select_different_obj(i1 %c, ptr %p, ptr %p2) { 837; CHECK-LABEL: @select_different_obj( 838; CHECK-NEXT: entry: 839; CHECK-NEXT: [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]] 840; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]] 841; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]] 842; CHECK: if: 843; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 844; CHECK-NEXT: call void @use_ptr(ptr [[P3]]) 845; CHECK-NEXT: ret void 846; CHECK: exit: 847; CHECK-NEXT: ret void 848; 849entry: 850 %p3 = select i1 %c, ptr %p, ptr %p2 851 %cmp = icmp eq ptr %p, %p3 852 br i1 %cmp, label %if, label %exit 853 854if: 855 call void @use_ptr(ptr %p) 856 call void @use_ptr(ptr %p3) 857 ret void 858 859exit: 860 ret void 861} 862 863define void @select_same_obj_is_select(i1 %c, ptr %p, ptr %p2, i64 %x) { 864; CHECK-LABEL: @select_same_obj_is_select( 865; CHECK-NEXT: entry: 866; CHECK-NEXT: [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]] 867; CHECK-NEXT: [[P4:%.*]] = getelementptr i8, ptr [[P3]], i64 [[X:%.*]] 868; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P3]], [[P4]] 869; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]] 870; CHECK: if: 871; CHECK-NEXT: call void @use_ptr(ptr [[P3]]) 872; CHECK-NEXT: call void @use_ptr(ptr [[P3]]) 873; CHECK-NEXT: ret void 874; CHECK: exit: 875; CHECK-NEXT: ret void 876; 877entry: 878 %p3 = select i1 %c, ptr %p, ptr %p2 879 %p4 = getelementptr i8, ptr %p3, i64 %x 880 %cmp = icmp eq ptr %p3, %p4 881 br i1 %cmp, label %if, label %exit 882 883if: 884 call void @use_ptr(ptr %p3) 885 call void @use_ptr(ptr %p4) 886 ret void 887 888exit: 889 ret void 890} 891 892define void @phi_same_obj(i1 %c, ptr %p, i64 %x) { 893; CHECK-LABEL: @phi_same_obj( 894; CHECK-NEXT: entry: 895; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X:%.*]] 896; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 897; CHECK: if: 898; CHECK-NEXT: br label [[JOIN]] 899; CHECK: join: 900; CHECK-NEXT: [[P3:%.*]] = phi ptr [ [[P]], [[IF]] ], [ [[P2]], [[ENTRY:%.*]] ] 901; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]] 902; CHECK-NEXT: br i1 [[CMP]], label [[IF2:%.*]], label [[EXIT:%.*]] 903; CHECK: if2: 904; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 905; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 906; CHECK-NEXT: ret void 907; CHECK: exit: 908; CHECK-NEXT: ret void 909; 910entry: 911 %p2 = getelementptr i8, ptr %p, i64 %x 912 br i1 %c, label %if, label %join 913 914if: 915 br label %join 916 917join: 918 %p3 = phi ptr [ %p, %if ], [ %p2, %entry ] 919 %cmp = icmp eq ptr %p, %p3 920 br i1 %cmp, label %if2, label %exit 921 922if2: 923 call void @use_ptr(ptr %p) 924 call void @use_ptr(ptr %p3) 925 ret void 926 927exit: 928 ret void 929} 930 931define void @phi_different_obj(i1 %c, ptr %p, ptr %p2) { 932; CHECK-LABEL: @phi_different_obj( 933; CHECK-NEXT: entry: 934; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 935; CHECK: if: 936; CHECK-NEXT: br label [[JOIN]] 937; CHECK: join: 938; CHECK-NEXT: [[P3:%.*]] = phi ptr [ [[P:%.*]], [[IF]] ], [ [[P2:%.*]], [[ENTRY:%.*]] ] 939; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]] 940; CHECK-NEXT: br i1 [[CMP]], label [[IF2:%.*]], label [[EXIT:%.*]] 941; CHECK: if2: 942; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 943; CHECK-NEXT: call void @use_ptr(ptr [[P3]]) 944; CHECK-NEXT: ret void 945; CHECK: exit: 946; CHECK-NEXT: ret void 947; 948entry: 949 br i1 %c, label %if, label %join 950 951if: 952 br label %join 953 954join: 955 %p3 = phi ptr [ %p, %if ], [ %p2, %entry ] 956 %cmp = icmp eq ptr %p, %p3 957 br i1 %cmp, label %if2, label %exit 958 959if2: 960 call void @use_ptr(ptr %p) 961 call void @use_ptr(ptr %p3) 962 ret void 963 964exit: 965 ret void 966} 967 968define void @phi_same_obj_cycle(i1 %c, ptr %p, i64 %x) { 969; CHECK-LABEL: @phi_same_obj_cycle( 970; CHECK-NEXT: entry: 971; CHECK-NEXT: br label [[LOOP:%.*]] 972; CHECK: loop: 973; CHECK-NEXT: [[P_IV:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 974; CHECK-NEXT: [[P_NEXT]] = getelementptr i8, ptr [[P_IV]], i64 [[X:%.*]] 975; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P_IV]], [[P]] 976; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[LOOP_LATCH]] 977; CHECK: if: 978; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 979; CHECK-NEXT: call void @use_ptr(ptr [[P]]) 980; CHECK-NEXT: br label [[LOOP_LATCH]] 981; CHECK: loop.latch: 982; CHECK-NEXT: br label [[LOOP]] 983; 984entry: 985 br label %loop 986 987loop: 988 %p.iv = phi ptr [ %p, %entry ], [ %p.next, %loop.latch ] 989 %p.next = getelementptr i8, ptr %p.iv, i64 %x 990 %cmp = icmp eq ptr %p.iv, %p 991 br i1 %cmp, label %if, label %loop.latch 992 993if: 994 call void @use_ptr(ptr %p.iv) 995 call void @use_ptr(ptr %p) 996 br label %loop.latch 997 998loop.latch: 999 br label %loop 1000} 1001 1002declare void @use_bool(i1) 1003declare void @use_ptr(ptr) 1004