1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -jump-threading < %s | FileCheck %s 3 4declare void @foo() 5declare void @bar() 6declare void @baz() 7declare void @quux() 8 9 10; Jump threading of branch with select as condition. 11; Mostly theoretical since instruction combining simplifies all selects of 12; booleans where at least one operand is true/false/undef. 13 14define void @test_br(i1 %cond, i1 %value) nounwind { 15; CHECK-LABEL: @test_br( 16; CHECK-NEXT: entry: 17; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L0:%.*]] 18; CHECK: L0: 19; CHECK-NEXT: call void @baz() 20; CHECK-NEXT: [[EXPR:%.*]] = select i1 [[COND]], i1 true, i1 [[VALUE:%.*]] 21; CHECK-NEXT: br i1 [[EXPR]], label [[L1]], label [[L2:%.*]] 22; CHECK: L1: 23; CHECK-NEXT: call void @foo() 24; CHECK-NEXT: ret void 25; CHECK: L2: 26; CHECK-NEXT: call void @bar() 27; CHECK-NEXT: ret void 28; 29entry: 30 br i1 %cond, label %L0, label %L3 31L0: 32 %expr = select i1 %cond, i1 true, i1 %value 33 br i1 %expr, label %L1, label %L2 34 35L1: 36 call void @foo() 37 ret void 38L2: 39 call void @bar() 40 ret void 41L3: 42 call void @baz() 43 br label %L0 44} 45 46 47; Jump threading of switch with select as condition. 48 49define void @test_switch(i1 %cond, i8 %value) nounwind { 50; CHECK-LABEL: @test_switch( 51; CHECK-NEXT: entry: 52; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L0:%.*]] 53; CHECK: L0: 54; CHECK-NEXT: call void @quux() 55; CHECK-NEXT: [[EXPR:%.*]] = select i1 [[COND]], i8 1, i8 [[VALUE:%.*]] 56; CHECK-NEXT: switch i8 [[EXPR]], label [[L3:%.*]] [ 57; CHECK-NEXT: i8 1, label [[L1]] 58; CHECK-NEXT: i8 2, label [[L2:%.*]] 59; CHECK-NEXT: ] 60; CHECK: L1: 61; CHECK-NEXT: call void @foo() 62; CHECK-NEXT: ret void 63; CHECK: L2: 64; CHECK-NEXT: call void @bar() 65; CHECK-NEXT: ret void 66; CHECK: L3: 67; CHECK-NEXT: call void @baz() 68; CHECK-NEXT: ret void 69; 70entry: 71 br i1 %cond, label %L0, label %L4 72L0: 73 %expr = select i1 %cond, i8 1, i8 %value 74 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2] 75 76L1: 77 call void @foo() 78 ret void 79L2: 80 call void @bar() 81 ret void 82L3: 83 call void @baz() 84 ret void 85L4: 86 call void @quux() 87 br label %L0 88} 89 90; Make sure the blocks in the indirectbr test aren't trivially removable as 91; successors by taking their addresses. 92@anchor = constant [3 x i8*] [ 93 i8* blockaddress(@test_indirectbr, %L1), 94 i8* blockaddress(@test_indirectbr, %L2), 95 i8* blockaddress(@test_indirectbr, %L3) 96] 97 98 99; Jump threading of indirectbr with select as address. 100 101define void @test_indirectbr(i1 %cond, i8* %address) nounwind { 102; CHECK-LABEL: @test_indirectbr( 103; CHECK-NEXT: entry: 104; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L3:%.*]] 105; CHECK: L1: 106; CHECK-NEXT: call void @foo() 107; CHECK-NEXT: ret void 108; CHECK: L3: 109; CHECK-NEXT: call void @baz() 110; CHECK-NEXT: ret void 111; 112entry: 113 br i1 %cond, label %L0, label %L3 114L0: 115 %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address 116 indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3] 117 118L1: 119 call void @foo() 120 ret void 121L2: 122 call void @bar() 123 ret void 124L3: 125 call void @baz() 126 ret void 127} 128 129 130; Jump threading of indirectbr with select as address. Test increased 131; duplication threshold for cases where indirectbr is being threaded 132; through. 133 134define void @test_indirectbr_thresh(i1 %cond, i8* %address) nounwind { 135; CHECK-LABEL: @test_indirectbr_thresh( 136; CHECK-NEXT: entry: 137; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L3:%.*]] 138; CHECK: L1: 139; CHECK-NEXT: call void @quux() 140; CHECK-NEXT: call void @quux() 141; CHECK-NEXT: call void @quux() 142; CHECK-NEXT: call void @foo() 143; CHECK-NEXT: ret void 144; CHECK: L3: 145; CHECK-NEXT: call void @baz() 146; CHECK-NEXT: ret void 147; 148entry: 149 br i1 %cond, label %L0, label %L3 150L0: 151 %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr_thresh, %L1), i8* %address 152 call void @quux() 153 call void @quux() 154 call void @quux() 155 indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3] 156 157L1: 158 call void @foo() 159 ret void 160L2: 161 call void @bar() 162 ret void 163L3: 164 call void @baz() 165 ret void 166} 167 168 169; A more complicated case: the condition is a select based on a comparison. 170 171define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind { 172; CHECK-LABEL: @test_switch_cmp( 173; CHECK-NEXT: entry: 174; CHECK-NEXT: br i1 [[COND:%.*]], label [[L0:%.*]], label [[L0_THREAD:%.*]] 175; CHECK: L0: 176; CHECK-NEXT: [[VAL_PHI:%.*]] = phi i32 [ [[VAL:%.*]], [[ENTRY:%.*]] ] 177; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[VAL_PHI]], 0 178; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[CMP]] 179; CHECK-NEXT: br i1 [[COND_FR]], label [[L1:%.*]], label [[TMP0:%.*]] 180; CHECK: 0: 181; CHECK-NEXT: [[TMP1:%.*]] = phi i8 [ [[VALUE:%.*]], [[L0]] ] 182; CHECK-NEXT: switch i8 [[TMP1]], label [[L3:%.*]] [ 183; CHECK-NEXT: i8 1, label [[L1]] 184; CHECK-NEXT: i8 2, label [[L2:%.*]] 185; CHECK-NEXT: ] 186; CHECK: L1: 187; CHECK-NEXT: call void @foo() 188; CHECK-NEXT: ret void 189; CHECK: L2: 190; CHECK-NEXT: call void @bar() 191; CHECK-NEXT: ret void 192; CHECK: L3: 193; CHECK-NEXT: call void @baz() 194; CHECK-NEXT: ret void 195; CHECK: L0.thread: 196; CHECK-NEXT: call void @quux() 197; CHECK-NEXT: br label [[L1]] 198; 199entry: 200 br i1 %cond, label %L0, label %L4 201L0: 202 %val.phi = phi i32 [%val, %entry], [-1, %L4] 203 %cmp = icmp slt i32 %val.phi, 0 204 %expr = select i1 %cmp, i8 1, i8 %value 205 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2] 206 207L1: 208 call void @foo() 209 ret void 210L2: 211 call void @bar() 212 ret void 213L3: 214 call void @baz() 215 ret void 216L4: 217 call void @quux() 218 br label %L0 219} 220 221; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is 222; reachable. 223define void @test_switch_default(i32* nocapture %status) nounwind { 224; CHECK-LABEL: @test_switch_default( 225; CHECK-NEXT: entry: 226; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[STATUS:%.*]], align 4 227; CHECK-NEXT: switch i32 [[TMP0]], label [[L2:%.*]] [ 228; CHECK-NEXT: i32 5061, label [[L2_THREAD:%.*]] 229; CHECK-NEXT: i32 0, label [[L2]] 230; CHECK-NEXT: ] 231; CHECK: L2.thread: 232; CHECK-NEXT: store i32 10025, i32* [[STATUS]], align 4 233; CHECK-NEXT: br label [[L4:%.*]] 234; CHECK: L2: 235; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP0]], [[ENTRY]] ] 236; CHECK-NEXT: [[CMP57_I:%.*]] = icmp eq i32 [[TMP1]], 0 237; CHECK-NEXT: br i1 [[CMP57_I]], label [[L3:%.*]], label [[L4]] 238; CHECK: L3: 239; CHECK-NEXT: store i32 10000, i32* [[STATUS]], align 4 240; CHECK-NEXT: br label [[L4]] 241; CHECK: L4: 242; CHECK-NEXT: ret void 243; 244entry: 245 %0 = load i32, i32* %status, align 4 246 switch i32 %0, label %L2 [ 247 i32 5061, label %L1 248 i32 0, label %L2 249 ] 250 251L1: 252 store i32 10025, i32* %status, align 4 253 br label %L2 254 255L2: 256 %1 = load i32, i32* %status, align 4 257 %cmp57.i = icmp eq i32 %1, 0 258 br i1 %cmp57.i, label %L3, label %L4 259 260L3: 261 store i32 10000, i32* %status, align 4 262 br label %L4 263 264L4: 265 ret void 266} 267 268define void @unfold1(double %x, double %y) nounwind { 269; CHECK-LABEL: @unfold1( 270; CHECK-NEXT: entry: 271; CHECK-NEXT: [[SUB:%.*]] = fsub double [[X:%.*]], [[Y:%.*]] 272; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[SUB]], 1.000000e+01 273; CHECK-NEXT: br i1 [[CMP]], label [[COND_END4:%.*]], label [[COND_FALSE:%.*]] 274; CHECK: cond.false: 275; CHECK-NEXT: [[ADD:%.*]] = fadd double [[X]], [[Y]] 276; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt double [[ADD]], 1.000000e+01 277; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END4]], label [[IF_THEN:%.*]] 278; CHECK: cond.end4: 279; CHECK-NEXT: [[COND5:%.*]] = phi double [ [[SUB]], [[ENTRY:%.*]] ], [ [[ADD]], [[COND_FALSE]] ] 280; CHECK-NEXT: [[CMP6:%.*]] = fcmp oeq double [[COND5]], 0.000000e+00 281; CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN]], label [[IF_END:%.*]] 282; CHECK: if.then: 283; CHECK-NEXT: call void @foo() 284; CHECK-NEXT: br label [[IF_END]] 285; CHECK: if.end: 286; CHECK-NEXT: ret void 287; 288entry: 289 %sub = fsub double %x, %y 290 %cmp = fcmp ogt double %sub, 1.000000e+01 291 br i1 %cmp, label %cond.end4, label %cond.false 292 293cond.false: ; preds = %entry 294 %add = fadd double %x, %y 295 %cmp1 = fcmp ogt double %add, 1.000000e+01 296 %add. = select i1 %cmp1, double %add, double 0.000000e+00 297 br label %cond.end4 298 299cond.end4: ; preds = %entry, %cond.false 300 %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ] 301 %cmp6 = fcmp oeq double %cond5, 0.000000e+00 302 br i1 %cmp6, label %if.then, label %if.end 303 304if.then: ; preds = %cond.end4 305 call void @foo() 306 br label %if.end 307 308if.end: ; preds = %if.then, %cond.end4 309 ret void 310 311} 312 313 314define void @unfold2(i32 %x, i32 %y) nounwind { 315; CHECK-LABEL: @unfold2( 316; CHECK-NEXT: entry: 317; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] 318; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], 10 319; CHECK-NEXT: br i1 [[CMP]], label [[IF_END:%.*]], label [[COND_FALSE:%.*]] 320; CHECK: cond.false: 321; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], [[Y]] 322; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[ADD]], 10 323; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[COND_END4:%.*]] 324; CHECK: cond.end4: 325; CHECK-NEXT: [[COND5:%.*]] = phi i32 [ [[ADD]], [[COND_FALSE]] ] 326; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[COND5]], 0 327; CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN]], label [[IF_END]] 328; CHECK: if.then: 329; CHECK-NEXT: call void @foo() 330; CHECK-NEXT: br label [[IF_END]] 331; CHECK: if.end: 332; CHECK-NEXT: ret void 333; 334entry: 335 %sub = sub nsw i32 %x, %y 336 %cmp = icmp sgt i32 %sub, 10 337 br i1 %cmp, label %cond.end4, label %cond.false 338 339cond.false: ; preds = %entry 340 %add = add nsw i32 %x, %y 341 %cmp1 = icmp sgt i32 %add, 10 342 %add. = select i1 %cmp1, i32 0, i32 %add 343 br label %cond.end4 344 345cond.end4: ; preds = %entry, %cond.false 346 %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ] 347 %cmp6 = icmp eq i32 %cond5, 0 348 br i1 %cmp6, label %if.then, label %if.end 349 350if.then: ; preds = %cond.end4 351 call void @foo() 352 br label %if.end 353 354if.end: ; preds = %if.then, %cond.end4 355 ret void 356 357} 358 359 360define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 361; CHECK-LABEL: @unfold3( 362; CHECK-NEXT: entry: 363; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 364; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 365; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT_THREAD4:%.*]], label [[COND_FALSE_I:%.*]] 366; CHECK: cond.false.i: 367; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 368; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT_THREAD:%.*]], label [[COND_FALSE_6_I:%.*]] 369; CHECK: cond.false.6.i: 370; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 371; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT_THREAD4]], label [[COND_FALSE_10_I:%.*]] 372; CHECK: cond.false.10.i: 373; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 374; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT_THREAD]], label [[DOTEXIT:%.*]] 375; CHECK: .exit: 376; CHECK-NEXT: [[PHITMP:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 377; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[PHITMP]] 378; CHECK-NEXT: br i1 [[COND_FR]], label [[DOTEXIT_THREAD]], label [[DOTEXIT_THREAD4]] 379; CHECK: .exit.thread: 380; CHECK-NEXT: br label [[DOTEXIT_THREAD4]] 381; CHECK: .exit.thread4: 382; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[J]], [[DOTEXIT_THREAD]] ], [ [[ADD3]], [[DOTEXIT]] ], [ [[ADD3]], [[ENTRY:%.*]] ], [ [[ADD3]], [[COND_FALSE_6_I]] ] 383; CHECK-NEXT: ret i32 [[TMP0]] 384; 385entry: 386 %add3 = add nsw i32 %j, 2 387 %cmp.i = icmp slt i32 %u, %v 388 br i1 %cmp.i, label %.exit, label %cond.false.i 389 390cond.false.i: ; preds = %entry 391 %cmp4.i = icmp sgt i32 %u, %v 392 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 393 394cond.false.6.i: ; preds = %cond.false.i 395 %cmp8.i = icmp slt i32 %w, %x 396 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 397 398cond.false.10.i: ; preds = %cond.false.6.i 399 %cmp13.i = icmp sgt i32 %w, %x 400 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 401 402cond.false.15.i: ; preds = %cond.false.10.i 403 %phitmp = icmp sge i32 %y, %z 404 br label %.exit 405 406.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 407 %cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ] 408 %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3 409 ret i32 %j.add3 410 411} 412 413define i32 @unfold4(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 414; CHECK-LABEL: @unfold4( 415; CHECK-NEXT: entry: 416; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 417; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 418; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT_THREAD:%.*]], label [[COND_FALSE_I:%.*]] 419; CHECK: cond.false.i: 420; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 421; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT_THREAD5:%.*]], label [[COND_FALSE_6_I:%.*]] 422; CHECK: cond.false.6.i: 423; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 424; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT_THREAD]], label [[COND_FALSE_10_I:%.*]] 425; CHECK: cond.false.10.i: 426; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 427; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT_THREAD5]], label [[DOTEXIT:%.*]] 428; CHECK: .exit: 429; CHECK-NEXT: [[CMP19_I:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 430; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP19_I]] to i32 431; CHECK-NEXT: [[LNOT_I18:%.*]] = icmp eq i32 [[CONV]], 1 432; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[LNOT_I18]] 433; CHECK-NEXT: br i1 [[COND_FR]], label [[DOTEXIT_THREAD]], label [[DOTEXIT_THREAD5]] 434; CHECK: .exit.thread: 435; CHECK-NEXT: br label [[DOTEXIT_THREAD5]] 436; CHECK: .exit.thread5: 437; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[J]], [[DOTEXIT_THREAD]] ], [ [[ADD3]], [[DOTEXIT]] ], [ [[ADD3]], [[COND_FALSE_I]] ], [ [[ADD3]], [[COND_FALSE_10_I]] ] 438; CHECK-NEXT: ret i32 [[TMP0]] 439; 440entry: 441 %add3 = add nsw i32 %j, 2 442 %cmp.i = icmp slt i32 %u, %v 443 br i1 %cmp.i, label %.exit, label %cond.false.i 444 445cond.false.i: ; preds = %entry 446 %cmp4.i = icmp sgt i32 %u, %v 447 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 448 449cond.false.6.i: ; preds = %cond.false.i 450 %cmp8.i = icmp slt i32 %w, %x 451 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 452 453cond.false.10.i: ; preds = %cond.false.6.i 454 %cmp13.i = icmp sgt i32 %w, %x 455 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 456 457cond.false.15.i: ; preds = %cond.false.10.i 458 %cmp19.i = icmp sge i32 %y, %z 459 %conv = zext i1 %cmp19.i to i32 460 br label %.exit 461 462.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 463 %cond23.i = phi i32 [ 1, %entry ], [ 0, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 0, %cond.false.10.i ] 464 %lnot.i18 = icmp eq i32 %cond23.i, 1 465 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %add3 466 ret i32 %j.add3 467 468} 469 470define i32 @unfold5(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 471; CHECK-LABEL: @unfold5( 472; CHECK-NEXT: entry: 473; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 474; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 475; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT:%.*]], label [[COND_FALSE_I:%.*]] 476; CHECK: cond.false.i: 477; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 478; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT]], label [[COND_FALSE_6_I:%.*]] 479; CHECK: cond.false.6.i: 480; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 481; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT]], label [[COND_FALSE_10_I:%.*]] 482; CHECK: cond.false.10.i: 483; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 484; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT]], label [[COND_FALSE_15_I:%.*]] 485; CHECK: cond.false.15.i: 486; CHECK-NEXT: [[CMP19_I:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 487; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP19_I]] to i32 488; CHECK-NEXT: br label [[DOTEXIT]] 489; CHECK: .exit: 490; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[J]], [[COND_FALSE_10_I]] ], [ [[CONV]], [[COND_FALSE_15_I]] ], [ 1, [[COND_FALSE_6_I]] ], [ 3, [[COND_FALSE_I]] ], [ 2, [[ENTRY:%.*]] ] 491; CHECK-NEXT: ret i32 [[TMP0]] 492; 493entry: 494 %add3 = add nsw i32 %j, 2 495 %cmp.i = icmp slt i32 %u, %v 496 br i1 %cmp.i, label %.exit, label %cond.false.i 497 498cond.false.i: ; preds = %entry 499 %cmp4.i = icmp sgt i32 %u, %v 500 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 501 502cond.false.6.i: ; preds = %cond.false.i 503 %cmp8.i = icmp slt i32 %w, %x 504 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 505 506cond.false.10.i: ; preds = %cond.false.6.i 507 %cmp13.i = icmp sgt i32 %w, %x 508 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 509 510cond.false.15.i: ; preds = %cond.false.10.i 511 %cmp19.i = icmp sge i32 %y, %z 512 %conv = zext i1 %cmp19.i to i32 513 br label %.exit 514 515.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 516 %cond23.i = phi i32 [ 2, %entry ], [ 3, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 7, %cond.false.10.i ] 517 %lnot.i18 = icmp sgt i32 %cond23.i, 5 518 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %cond23.i 519 ret i32 %j.add3 520 521} 522 523; When a select has a constant operand in one branch, and it feeds a phi node 524; and the phi node feeds a switch we unfold the select 525define void @test_func(i32* nocapture readonly %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %n) local_unnamed_addr #0 { 526; CHECK-LABEL: @test_func( 527; CHECK-NEXT: entry: 528; CHECK-NEXT: br label [[FOR_COND:%.*]] 529; CHECK: for.cond: 530; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_DEFAULT:%.*]] ] 531; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N:%.*]] 532; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] 533; CHECK: for.cond.cleanup: 534; CHECK-NEXT: ret void 535; CHECK: for.body: 536; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[I_0]] to i64 537; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[TMP0]] 538; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 539; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP1]], 4 540; CHECK-NEXT: br i1 [[CMP1]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]] 541; CHECK: land.lhs.true: 542; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[TMP0]] 543; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX3]], align 4 544; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* [[C:%.*]], i64 [[TMP0]] 545; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[ARRAYIDX5]], align 4 546; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[TMP2]], [[TMP3]] 547; CHECK-NEXT: br i1 [[CMP6]], label [[SW_BB:%.*]], label [[SW_BB7:%.*]] 548; CHECK: if.end: 549; CHECK-NEXT: [[LOCAL_VAR_0:%.*]] = phi i32 [ [[TMP1]], [[FOR_BODY]] ] 550; CHECK-NEXT: switch i32 [[LOCAL_VAR_0]], label [[SW_DEFAULT]] [ 551; CHECK-NEXT: i32 2, label [[SW_BB]] 552; CHECK-NEXT: i32 4, label [[SW_BB7]] 553; CHECK-NEXT: i32 5, label [[SW_BB8:%.*]] 554; CHECK-NEXT: i32 7, label [[SW_BB9:%.*]] 555; CHECK-NEXT: ] 556; CHECK: sw.bb: 557; CHECK-NEXT: call void @foo() 558; CHECK-NEXT: br label [[SW_BB7]] 559; CHECK: sw.bb7: 560; CHECK-NEXT: call void @bar() 561; CHECK-NEXT: br label [[SW_BB8]] 562; CHECK: sw.bb8: 563; CHECK-NEXT: call void @baz() 564; CHECK-NEXT: br label [[SW_BB9]] 565; CHECK: sw.bb9: 566; CHECK-NEXT: call void @quux() 567; CHECK-NEXT: br label [[SW_DEFAULT]] 568; CHECK: sw.default: 569; CHECK-NEXT: call void @baz() 570; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_0]], 1 571; CHECK-NEXT: br label [[FOR_COND]] 572; 573entry: 574 br label %for.cond 575 576for.cond: ; preds = %sw.default, %entry 577 %i.0 = phi i32 [ 0, %entry ], [ %inc, %sw.default ] 578 %cmp = icmp slt i32 %i.0, %n 579 br i1 %cmp, label %for.body, label %for.cond.cleanup 580 581for.cond.cleanup: ; preds = %for.cond 582 ret void 583 584for.body: ; preds = %for.cond 585 %0 = zext i32 %i.0 to i64 586 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %0 587 %1 = load i32, i32* %arrayidx, align 4 588 %cmp1 = icmp eq i32 %1, 4 589 br i1 %cmp1, label %land.lhs.true, label %if.end 590 591land.lhs.true: ; preds = %for.body 592 %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %0 593 %2 = load i32, i32* %arrayidx3, align 4 594 %arrayidx5 = getelementptr inbounds i32, i32* %c, i64 %0 595 %3 = load i32, i32* %arrayidx5, align 4 596 %cmp6 = icmp eq i32 %2, %3 597 %spec.select = select i1 %cmp6, i32 2, i32 4 598 br label %if.end 599 600if.end: ; preds = %land.lhs.true, %for.body 601 %local_var.0 = phi i32 [ %1, %for.body ], [ %spec.select, %land.lhs.true ] 602 switch i32 %local_var.0, label %sw.default [ 603 i32 2, label %sw.bb 604 i32 4, label %sw.bb7 605 i32 5, label %sw.bb8 606 i32 7, label %sw.bb9 607 ] 608 609sw.bb: ; preds = %if.end 610 call void @foo() 611 br label %sw.bb7 612 613sw.bb7: ; preds = %if.end, %sw.bb 614 call void @bar() 615 br label %sw.bb8 616 617sw.bb8: ; preds = %if.end, %sw.bb7 618 call void @baz() 619 br label %sw.bb9 620 621sw.bb9: ; preds = %if.end, %sw.bb8 622 call void @quux() 623 br label %sw.default 624 625sw.default: ; preds = %if.end, %sw.bb9 626 call void @baz() 627 %inc = add nuw nsw i32 %i.0, 1 628 br label %for.cond 629} 630 631define i32 @TryToUnfoldSelectInCurrBB(i1 %b, i1 %ui, i32 %s, i1 %x) { 632; CHECK-LABEL: @TryToUnfoldSelectInCurrBB( 633; CHECK-NEXT: entry: 634; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_END_THREAD:%.*]], label [[IF_END:%.*]] 635; CHECK: if.end: 636; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[X:%.*]] 637; CHECK-NEXT: br i1 [[COND_FR]], label [[TMP0:%.*]], label [[IF_END_THREAD]] 638; CHECK: 0: 639; CHECK-NEXT: br label [[IF_END_THREAD]] 640; CHECK: if.end.thread: 641; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[S:%.*]], [[TMP0]] ], [ 42, [[IF_END]] ], [ 42, [[ENTRY:%.*]] ] 642; CHECK-NEXT: ret i32 [[TMP1]] 643; 644entry: 645 br i1 %b, label %if.end, label %if.else 646 647if.else: 648 br label %if.end 649 650if.end: 651 %v = phi i1 [ %x, %if.else ], [ false, %entry ] 652 %v1 = select i1 %v, i32 %s, i32 42 653 ret i32 %v1 654} 655