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: br i1 [[CMP]], label [[L1:%.*]], label [[TMP0:%.*]] 179; CHECK: 0: 180; CHECK-NEXT: [[TMP1:%.*]] = phi i8 [ [[VALUE:%.*]], [[L0]] ] 181; CHECK-NEXT: switch i8 [[TMP1]], label [[L3:%.*]] [ 182; CHECK-NEXT: i8 1, label [[L1]] 183; CHECK-NEXT: i8 2, label [[L2:%.*]] 184; CHECK-NEXT: ] 185; CHECK: L1: 186; CHECK-NEXT: call void @foo() 187; CHECK-NEXT: ret void 188; CHECK: L2: 189; CHECK-NEXT: call void @bar() 190; CHECK-NEXT: ret void 191; CHECK: L3: 192; CHECK-NEXT: call void @baz() 193; CHECK-NEXT: ret void 194; CHECK: L0.thread: 195; CHECK-NEXT: call void @quux() 196; CHECK-NEXT: br label [[L1]] 197; 198entry: 199 br i1 %cond, label %L0, label %L4 200L0: 201 %val.phi = phi i32 [%val, %entry], [-1, %L4] 202 %cmp = icmp slt i32 %val.phi, 0 203 %expr = select i1 %cmp, i8 1, i8 %value 204 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2] 205 206L1: 207 call void @foo() 208 ret void 209L2: 210 call void @bar() 211 ret void 212L3: 213 call void @baz() 214 ret void 215L4: 216 call void @quux() 217 br label %L0 218} 219 220; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is 221; reachable. 222define void @test_switch_default(i32* nocapture %status) nounwind { 223; CHECK-LABEL: @test_switch_default( 224; CHECK-NEXT: entry: 225; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[STATUS:%.*]], align 4 226; CHECK-NEXT: switch i32 [[TMP0]], label [[L2:%.*]] [ 227; CHECK-NEXT: i32 5061, label [[L2_THREAD:%.*]] 228; CHECK-NEXT: i32 0, label [[L2]] 229; CHECK-NEXT: ] 230; CHECK: L2.thread: 231; CHECK-NEXT: store i32 10025, i32* [[STATUS]], align 4 232; CHECK-NEXT: br label [[L4:%.*]] 233; CHECK: L2: 234; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP0]], [[ENTRY]] ] 235; CHECK-NEXT: [[CMP57_I:%.*]] = icmp eq i32 [[TMP1]], 0 236; CHECK-NEXT: br i1 [[CMP57_I]], label [[L3:%.*]], label [[L4]] 237; CHECK: L3: 238; CHECK-NEXT: store i32 10000, i32* [[STATUS]], align 4 239; CHECK-NEXT: br label [[L4]] 240; CHECK: L4: 241; CHECK-NEXT: ret void 242; 243entry: 244 %0 = load i32, i32* %status, align 4 245 switch i32 %0, label %L2 [ 246 i32 5061, label %L1 247 i32 0, label %L2 248 ] 249 250L1: 251 store i32 10025, i32* %status, align 4 252 br label %L2 253 254L2: 255 %1 = load i32, i32* %status, align 4 256 %cmp57.i = icmp eq i32 %1, 0 257 br i1 %cmp57.i, label %L3, label %L4 258 259L3: 260 store i32 10000, i32* %status, align 4 261 br label %L4 262 263L4: 264 ret void 265} 266 267define void @unfold1(double %x, double %y) nounwind { 268; CHECK-LABEL: @unfold1( 269; CHECK-NEXT: entry: 270; CHECK-NEXT: [[SUB:%.*]] = fsub double [[X:%.*]], [[Y:%.*]] 271; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[SUB]], 1.000000e+01 272; CHECK-NEXT: br i1 [[CMP]], label [[COND_END4:%.*]], label [[COND_FALSE:%.*]] 273; CHECK: cond.false: 274; CHECK-NEXT: [[ADD:%.*]] = fadd double [[X]], [[Y]] 275; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt double [[ADD]], 1.000000e+01 276; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END4]], label [[IF_THEN:%.*]] 277; CHECK: cond.end4: 278; CHECK-NEXT: [[COND5:%.*]] = phi double [ [[SUB]], [[ENTRY:%.*]] ], [ [[ADD]], [[COND_FALSE]] ] 279; CHECK-NEXT: [[CMP6:%.*]] = fcmp oeq double [[COND5]], 0.000000e+00 280; CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN]], label [[IF_END:%.*]] 281; CHECK: if.then: 282; CHECK-NEXT: call void @foo() 283; CHECK-NEXT: br label [[IF_END]] 284; CHECK: if.end: 285; CHECK-NEXT: ret void 286; 287entry: 288 %sub = fsub double %x, %y 289 %cmp = fcmp ogt double %sub, 1.000000e+01 290 br i1 %cmp, label %cond.end4, label %cond.false 291 292cond.false: ; preds = %entry 293 %add = fadd double %x, %y 294 %cmp1 = fcmp ogt double %add, 1.000000e+01 295 %add. = select i1 %cmp1, double %add, double 0.000000e+00 296 br label %cond.end4 297 298cond.end4: ; preds = %entry, %cond.false 299 %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ] 300 %cmp6 = fcmp oeq double %cond5, 0.000000e+00 301 br i1 %cmp6, label %if.then, label %if.end 302 303if.then: ; preds = %cond.end4 304 call void @foo() 305 br label %if.end 306 307if.end: ; preds = %if.then, %cond.end4 308 ret void 309 310} 311 312 313define void @unfold2(i32 %x, i32 %y) nounwind { 314; CHECK-LABEL: @unfold2( 315; CHECK-NEXT: entry: 316; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] 317; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], 10 318; CHECK-NEXT: br i1 [[CMP]], label [[IF_END:%.*]], label [[COND_FALSE:%.*]] 319; CHECK: cond.false: 320; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], [[Y]] 321; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[ADD]], 10 322; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[COND_END4:%.*]] 323; CHECK: cond.end4: 324; CHECK-NEXT: [[COND5:%.*]] = phi i32 [ [[ADD]], [[COND_FALSE]] ] 325; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[COND5]], 0 326; CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN]], label [[IF_END]] 327; CHECK: if.then: 328; CHECK-NEXT: call void @foo() 329; CHECK-NEXT: br label [[IF_END]] 330; CHECK: if.end: 331; CHECK-NEXT: ret void 332; 333entry: 334 %sub = sub nsw i32 %x, %y 335 %cmp = icmp sgt i32 %sub, 10 336 br i1 %cmp, label %cond.end4, label %cond.false 337 338cond.false: ; preds = %entry 339 %add = add nsw i32 %x, %y 340 %cmp1 = icmp sgt i32 %add, 10 341 %add. = select i1 %cmp1, i32 0, i32 %add 342 br label %cond.end4 343 344cond.end4: ; preds = %entry, %cond.false 345 %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ] 346 %cmp6 = icmp eq i32 %cond5, 0 347 br i1 %cmp6, label %if.then, label %if.end 348 349if.then: ; preds = %cond.end4 350 call void @foo() 351 br label %if.end 352 353if.end: ; preds = %if.then, %cond.end4 354 ret void 355 356} 357 358 359define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 360; CHECK-LABEL: @unfold3( 361; CHECK-NEXT: entry: 362; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 363; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 364; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT_THREAD3:%.*]], label [[COND_FALSE_I:%.*]] 365; CHECK: cond.false.i: 366; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 367; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT_THREAD:%.*]], label [[COND_FALSE_6_I:%.*]] 368; CHECK: cond.false.6.i: 369; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 370; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT_THREAD3]], label [[COND_FALSE_10_I:%.*]] 371; CHECK: cond.false.10.i: 372; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 373; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT_THREAD]], label [[DOTEXIT:%.*]] 374; CHECK: .exit: 375; CHECK-NEXT: [[PHITMP:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 376; CHECK-NEXT: br i1 [[PHITMP]], label [[DOTEXIT_THREAD]], label [[DOTEXIT_THREAD3]] 377; CHECK: .exit.thread: 378; CHECK-NEXT: br label [[DOTEXIT_THREAD3]] 379; CHECK: .exit.thread3: 380; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[J]], [[DOTEXIT_THREAD]] ], [ [[ADD3]], [[DOTEXIT]] ], [ [[ADD3]], [[ENTRY:%.*]] ], [ [[ADD3]], [[COND_FALSE_6_I]] ] 381; CHECK-NEXT: ret i32 [[TMP0]] 382; 383entry: 384 %add3 = add nsw i32 %j, 2 385 %cmp.i = icmp slt i32 %u, %v 386 br i1 %cmp.i, label %.exit, label %cond.false.i 387 388cond.false.i: ; preds = %entry 389 %cmp4.i = icmp sgt i32 %u, %v 390 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 391 392cond.false.6.i: ; preds = %cond.false.i 393 %cmp8.i = icmp slt i32 %w, %x 394 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 395 396cond.false.10.i: ; preds = %cond.false.6.i 397 %cmp13.i = icmp sgt i32 %w, %x 398 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 399 400cond.false.15.i: ; preds = %cond.false.10.i 401 %phitmp = icmp sge i32 %y, %z 402 br label %.exit 403 404.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 405 %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 ] 406 %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3 407 ret i32 %j.add3 408 409} 410 411define i32 @unfold4(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 412; CHECK-LABEL: @unfold4( 413; CHECK-NEXT: entry: 414; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 415; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 416; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT_THREAD:%.*]], label [[COND_FALSE_I:%.*]] 417; CHECK: cond.false.i: 418; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 419; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT_THREAD4:%.*]], label [[COND_FALSE_6_I:%.*]] 420; CHECK: cond.false.6.i: 421; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 422; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT_THREAD]], label [[COND_FALSE_10_I:%.*]] 423; CHECK: cond.false.10.i: 424; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 425; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT_THREAD4]], label [[DOTEXIT:%.*]] 426; CHECK: .exit: 427; CHECK-NEXT: [[CMP19_I:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 428; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP19_I]] to i32 429; CHECK-NEXT: [[LNOT_I18:%.*]] = icmp eq i32 [[CONV]], 1 430; CHECK-NEXT: br i1 [[LNOT_I18]], label [[DOTEXIT_THREAD]], label [[DOTEXIT_THREAD4]] 431; CHECK: .exit.thread: 432; CHECK-NEXT: br label [[DOTEXIT_THREAD4]] 433; CHECK: .exit.thread4: 434; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[J]], [[DOTEXIT_THREAD]] ], [ [[ADD3]], [[DOTEXIT]] ], [ [[ADD3]], [[COND_FALSE_I]] ], [ [[ADD3]], [[COND_FALSE_10_I]] ] 435; CHECK-NEXT: ret i32 [[TMP0]] 436; 437entry: 438 %add3 = add nsw i32 %j, 2 439 %cmp.i = icmp slt i32 %u, %v 440 br i1 %cmp.i, label %.exit, label %cond.false.i 441 442cond.false.i: ; preds = %entry 443 %cmp4.i = icmp sgt i32 %u, %v 444 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 445 446cond.false.6.i: ; preds = %cond.false.i 447 %cmp8.i = icmp slt i32 %w, %x 448 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 449 450cond.false.10.i: ; preds = %cond.false.6.i 451 %cmp13.i = icmp sgt i32 %w, %x 452 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 453 454cond.false.15.i: ; preds = %cond.false.10.i 455 %cmp19.i = icmp sge i32 %y, %z 456 %conv = zext i1 %cmp19.i to i32 457 br label %.exit 458 459.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 460 %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 ] 461 %lnot.i18 = icmp eq i32 %cond23.i, 1 462 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %add3 463 ret i32 %j.add3 464 465} 466 467define i32 @unfold5(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { 468; CHECK-LABEL: @unfold5( 469; CHECK-NEXT: entry: 470; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[J:%.*]], 2 471; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[U:%.*]], [[V:%.*]] 472; CHECK-NEXT: br i1 [[CMP_I]], label [[DOTEXIT:%.*]], label [[COND_FALSE_I:%.*]] 473; CHECK: cond.false.i: 474; CHECK-NEXT: [[CMP4_I:%.*]] = icmp sgt i32 [[U]], [[V]] 475; CHECK-NEXT: br i1 [[CMP4_I]], label [[DOTEXIT]], label [[COND_FALSE_6_I:%.*]] 476; CHECK: cond.false.6.i: 477; CHECK-NEXT: [[CMP8_I:%.*]] = icmp slt i32 [[W:%.*]], [[X:%.*]] 478; CHECK-NEXT: br i1 [[CMP8_I]], label [[DOTEXIT]], label [[COND_FALSE_10_I:%.*]] 479; CHECK: cond.false.10.i: 480; CHECK-NEXT: [[CMP13_I:%.*]] = icmp sgt i32 [[W]], [[X]] 481; CHECK-NEXT: br i1 [[CMP13_I]], label [[DOTEXIT]], label [[COND_FALSE_15_I:%.*]] 482; CHECK: cond.false.15.i: 483; CHECK-NEXT: [[CMP19_I:%.*]] = icmp sge i32 [[Y:%.*]], [[Z:%.*]] 484; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP19_I]] to i32 485; CHECK-NEXT: br label [[DOTEXIT]] 486; CHECK: .exit: 487; 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:%.*]] ] 488; CHECK-NEXT: ret i32 [[TMP0]] 489; 490entry: 491 %add3 = add nsw i32 %j, 2 492 %cmp.i = icmp slt i32 %u, %v 493 br i1 %cmp.i, label %.exit, label %cond.false.i 494 495cond.false.i: ; preds = %entry 496 %cmp4.i = icmp sgt i32 %u, %v 497 br i1 %cmp4.i, label %.exit, label %cond.false.6.i 498 499cond.false.6.i: ; preds = %cond.false.i 500 %cmp8.i = icmp slt i32 %w, %x 501 br i1 %cmp8.i, label %.exit, label %cond.false.10.i 502 503cond.false.10.i: ; preds = %cond.false.6.i 504 %cmp13.i = icmp sgt i32 %w, %x 505 br i1 %cmp13.i, label %.exit, label %cond.false.15.i 506 507cond.false.15.i: ; preds = %cond.false.10.i 508 %cmp19.i = icmp sge i32 %y, %z 509 %conv = zext i1 %cmp19.i to i32 510 br label %.exit 511 512.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i 513 %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 ] 514 %lnot.i18 = icmp sgt i32 %cond23.i, 5 515 %j.add3 = select i1 %lnot.i18, i32 %j, i32 %cond23.i 516 ret i32 %j.add3 517 518} 519 520; When a select has a constant operand in one branch, and it feeds a phi node 521; and the phi node feeds a switch we unfold the select 522define void @test_func(i32* nocapture readonly %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %n) local_unnamed_addr #0 { 523; CHECK-LABEL: @test_func( 524; CHECK-NEXT: entry: 525; CHECK-NEXT: br label [[FOR_COND:%.*]] 526; CHECK: for.cond: 527; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_DEFAULT:%.*]] ] 528; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N:%.*]] 529; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] 530; CHECK: for.cond.cleanup: 531; CHECK-NEXT: ret void 532; CHECK: for.body: 533; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[I_0]] to i64 534; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[TMP0]] 535; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 536; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP1]], 4 537; CHECK-NEXT: br i1 [[CMP1]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]] 538; CHECK: land.lhs.true: 539; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[TMP0]] 540; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX3]], align 4 541; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* [[C:%.*]], i64 [[TMP0]] 542; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[ARRAYIDX5]], align 4 543; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[TMP2]], [[TMP3]] 544; CHECK-NEXT: br i1 [[CMP6]], label [[SW_BB:%.*]], label [[SW_BB7:%.*]] 545; CHECK: if.end: 546; CHECK-NEXT: [[LOCAL_VAR_0:%.*]] = phi i32 [ [[TMP1]], [[FOR_BODY]] ] 547; CHECK-NEXT: switch i32 [[LOCAL_VAR_0]], label [[SW_DEFAULT]] [ 548; CHECK-NEXT: i32 2, label [[SW_BB]] 549; CHECK-NEXT: i32 4, label [[SW_BB7]] 550; CHECK-NEXT: i32 5, label [[SW_BB8:%.*]] 551; CHECK-NEXT: i32 7, label [[SW_BB9:%.*]] 552; CHECK-NEXT: ] 553; CHECK: sw.bb: 554; CHECK-NEXT: call void @foo() 555; CHECK-NEXT: br label [[SW_BB7]] 556; CHECK: sw.bb7: 557; CHECK-NEXT: call void @bar() 558; CHECK-NEXT: br label [[SW_BB8]] 559; CHECK: sw.bb8: 560; CHECK-NEXT: call void @baz() 561; CHECK-NEXT: br label [[SW_BB9]] 562; CHECK: sw.bb9: 563; CHECK-NEXT: call void @quux() 564; CHECK-NEXT: br label [[SW_DEFAULT]] 565; CHECK: sw.default: 566; CHECK-NEXT: call void @baz() 567; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_0]], 1 568; CHECK-NEXT: br label [[FOR_COND]] 569; 570entry: 571 br label %for.cond 572 573for.cond: ; preds = %sw.default, %entry 574 %i.0 = phi i32 [ 0, %entry ], [ %inc, %sw.default ] 575 %cmp = icmp slt i32 %i.0, %n 576 br i1 %cmp, label %for.body, label %for.cond.cleanup 577 578for.cond.cleanup: ; preds = %for.cond 579 ret void 580 581for.body: ; preds = %for.cond 582 %0 = zext i32 %i.0 to i64 583 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %0 584 %1 = load i32, i32* %arrayidx, align 4 585 %cmp1 = icmp eq i32 %1, 4 586 br i1 %cmp1, label %land.lhs.true, label %if.end 587 588land.lhs.true: ; preds = %for.body 589 %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %0 590 %2 = load i32, i32* %arrayidx3, align 4 591 %arrayidx5 = getelementptr inbounds i32, i32* %c, i64 %0 592 %3 = load i32, i32* %arrayidx5, align 4 593 %cmp6 = icmp eq i32 %2, %3 594 %spec.select = select i1 %cmp6, i32 2, i32 4 595 br label %if.end 596 597if.end: ; preds = %land.lhs.true, %for.body 598 %local_var.0 = phi i32 [ %1, %for.body ], [ %spec.select, %land.lhs.true ] 599 switch i32 %local_var.0, label %sw.default [ 600 i32 2, label %sw.bb 601 i32 4, label %sw.bb7 602 i32 5, label %sw.bb8 603 i32 7, label %sw.bb9 604 ] 605 606sw.bb: ; preds = %if.end 607 call void @foo() 608 br label %sw.bb7 609 610sw.bb7: ; preds = %if.end, %sw.bb 611 call void @bar() 612 br label %sw.bb8 613 614sw.bb8: ; preds = %if.end, %sw.bb7 615 call void @baz() 616 br label %sw.bb9 617 618sw.bb9: ; preds = %if.end, %sw.bb8 619 call void @quux() 620 br label %sw.default 621 622sw.default: ; preds = %if.end, %sw.bb9 623 call void @baz() 624 %inc = add nuw nsw i32 %i.0, 1 625 br label %for.cond 626} 627 628; FIXME: This is an invalid transform. If %b is false and %x is poison, 629; then the select produces poison (the result of the program is poison). 630; But with this transform, we may be branching on poison, and that is UB. 631 632define i32 @TryToUnfoldSelectInCurrBB(i1 %b, i1 %ui, i32 %s, i1 %x) { 633; CHECK-LABEL: @TryToUnfoldSelectInCurrBB( 634; CHECK-NEXT: entry: 635; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_END_THREAD:%.*]], label [[IF_END:%.*]] 636; CHECK: if.end: 637; CHECK-NEXT: br i1 [[X:%.*]], 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