759 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=unify-loop-exits -max-booleans-in-control-flow-hub=1 -S | FileCheck %s3; RUN: opt < %s -passes=unify-loop-exits -S | FileCheck --check-prefix=BOOLEAN %s4 5; A loop with multiple exit blocks.6 7define void @loop_two_exits(i1 %PredEntry, i1 %PredA) {8; CHECK-LABEL: @loop_two_exits(9; CHECK-NEXT: entry:10; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[E:%.*]]11; CHECK: A:12; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]13; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[LOOP_EXIT_GUARD:%.*]], label [[C]]14; CHECK: B:15; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0:[0-9]+]]16; CHECK-NEXT: br label [[D:%.*]]17; CHECK: C:18; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 119; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 1020; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]21; CHECK: D:22; CHECK-NEXT: unreachable23; CHECK: E:24; CHECK-NEXT: ret void25; CHECK: loop.exit.guard:26; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A]] ], [ 1, [[C]] ]27; CHECK-NEXT: [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 028; CHECK-NEXT: br i1 [[B_PREDICATE]], label [[B:%.*]], label [[E]]29;30; BOOLEAN-LABEL: @loop_two_exits(31; BOOLEAN-NEXT: entry:32; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[E:%.*]]33; BOOLEAN: A:34; BOOLEAN-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]35; BOOLEAN-NEXT: br i1 [[PREDA:%.*]], label [[LOOP_EXIT_GUARD:%.*]], label [[C]]36; BOOLEAN: B:37; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0:[0-9]+]]38; BOOLEAN-NEXT: br label [[D:%.*]]39; BOOLEAN: C:40; BOOLEAN-NEXT: [[INC2]] = add i32 [[INC1]], 141; BOOLEAN-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 1042; BOOLEAN-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]43; BOOLEAN: D:44; BOOLEAN-NEXT: unreachable45; BOOLEAN: E:46; BOOLEAN-NEXT: ret void47; BOOLEAN: loop.exit.guard:48; BOOLEAN-NEXT: [[GUARD_B:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ]49; BOOLEAN-NEXT: br i1 [[GUARD_B]], label [[B:%.*]], label [[E]]50;51entry:52 br i1 %PredEntry, label %A, label %E53 54A:55 %inc1 = phi i32 [ 0, %entry ], [ %inc2, %C ]56 br i1 %PredA, label %B, label %C57 58B:59 tail call fastcc void @check(i32 1) #060 br label %D61 62C:63 %inc2 = add i32 %inc1, 164 %cmp = icmp ult i32 %inc2, 1065 br i1 %cmp, label %A, label %E66 67D:68 unreachable69 70E:71 ret void72}73 74define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {75; CHECK-LABEL: @loop_two_exits_callbr(76; CHECK-NEXT: entry:77; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[E:%.*]]78; CHECK: A:79; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]80; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])81; CHECK-NEXT: to label [[A_TARGET_B:%.*]] [label %C]82; CHECK: B:83; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]84; CHECK-NEXT: br label [[D:%.*]]85; CHECK: C:86; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 187; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 1088; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[CMP]])89; CHECK-NEXT: to label [[A]] [label %C.target.E]90; CHECK: D:91; CHECK-NEXT: unreachable92; CHECK: E:93; CHECK-NEXT: ret void94; CHECK: A.target.B:95; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]96; CHECK: C.target.E:97; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]98; CHECK: loop.exit.guard:99; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_E:%.*]] ]100; CHECK-NEXT: [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0101; CHECK-NEXT: br i1 [[B_PREDICATE]], label [[B:%.*]], label [[E]]102;103; BOOLEAN-LABEL: @loop_two_exits_callbr(104; BOOLEAN-NEXT: entry:105; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[E:%.*]]106; BOOLEAN: A:107; BOOLEAN-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]108; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])109; BOOLEAN-NEXT: to label [[A_TARGET_B:%.*]] [label %C]110; BOOLEAN: B:111; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]112; BOOLEAN-NEXT: br label [[D:%.*]]113; BOOLEAN: C:114; BOOLEAN-NEXT: [[INC2]] = add i32 [[INC1]], 1115; BOOLEAN-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10116; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[CMP]])117; BOOLEAN-NEXT: to label [[A]] [label %C.target.E]118; BOOLEAN: D:119; BOOLEAN-NEXT: unreachable120; BOOLEAN: E:121; BOOLEAN-NEXT: ret void122; BOOLEAN: A.target.B:123; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]124; BOOLEAN: C.target.E:125; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]126; BOOLEAN: loop.exit.guard:127; BOOLEAN-NEXT: [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_E:%.*]] ]128; BOOLEAN-NEXT: br i1 [[GUARD_B]], label [[B:%.*]], label [[E]]129;130entry:131 br i1 %PredEntry, label %A, label %E132 133A:134 %inc1 = phi i32 [ 0, %entry ], [ %inc2, %C ]135 callbr void asm "", "r,!i"(i1 %PredA) to label %B [label %C]136 137B:138 tail call fastcc void @check(i32 1) #0139 br label %D140 141C:142 %inc2 = add i32 %inc1, 1143 %cmp = icmp ult i32 %inc2, 10144 callbr void asm "","r,!i"(i1 %cmp) to label %A [label %E]145 146D:147 unreachable148 149E:150 ret void151}152 153; The loop exit blocks appear in an inner loop.154 155define void @inner_loop(i1 %PredEntry, i1 %PredA, i1 %PredB) {156; CHECK-LABEL: @inner_loop(157; CHECK-NEXT: entry:158; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]159; CHECK: A:160; CHECK-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]161; CHECK-NEXT: br label [[B:%.*]]162; CHECK: B:163; CHECK-NEXT: [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]164; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]165; CHECK: C:166; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]167; CHECK-NEXT: br label [[H:%.*]]168; CHECK: D:169; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[LOOP_EXIT_GUARD2]], label [[F]]170; CHECK: E:171; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]172; CHECK-NEXT: br label [[H]]173; CHECK: F:174; CHECK-NEXT: [[INNER2]] = add i32 [[INNER1]], 1175; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20176; CHECK-NEXT: br i1 [[CMP1]], label [[B]], label [[LOOP_EXIT_GUARD2]]177; CHECK: G:178; CHECK-NEXT: [[OUTER2]] = add i32 [[OUTER1]], 1179; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10180; CHECK-NEXT: br i1 [[CMP2]], label [[A]], label [[LOOP_EXIT_GUARD:%.*]]181; CHECK: H:182; CHECK-NEXT: unreachable183; CHECK: I:184; CHECK-NEXT: ret void185; CHECK: loop.exit.guard:186; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 2, [[G]] ], [ [[MERGED_BB_IDX_MOVED:%.*]], [[LOOP_EXIT_GUARD2]] ]187; CHECK-NEXT: [[C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0188; CHECK-NEXT: br i1 [[C_PREDICATE]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]189; CHECK: loop.exit.guard1:190; CHECK-NEXT: [[E_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1191; CHECK-NEXT: br i1 [[E_PREDICATE]], label [[E:%.*]], label [[I]]192; CHECK: loop.exit.guard2:193; CHECK-NEXT: [[MERGED_BB_IDX_MOVED]] = phi i32 [ 0, [[B]] ], [ 1, [[D]] ], [ poison, [[F]] ]194; CHECK-NEXT: [[MERGED_BB_IDX3:%.*]] = phi i32 [ 0, [[B]] ], [ 0, [[D]] ], [ 1, [[F]] ]195; CHECK-NEXT: [[LOOP_EXIT_GUARD_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX3]], 0196; CHECK-NEXT: br i1 [[LOOP_EXIT_GUARD_PREDICATE]], label [[LOOP_EXIT_GUARD]], label [[G]]197;198; BOOLEAN-LABEL: @inner_loop(199; BOOLEAN-NEXT: entry:200; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]201; BOOLEAN: A:202; BOOLEAN-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]203; BOOLEAN-NEXT: br label [[B:%.*]]204; BOOLEAN: B:205; BOOLEAN-NEXT: [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]206; BOOLEAN-NEXT: br i1 [[PREDA:%.*]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]207; BOOLEAN: C:208; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]209; BOOLEAN-NEXT: br label [[H:%.*]]210; BOOLEAN: D:211; BOOLEAN-NEXT: br i1 [[PREDB:%.*]], label [[LOOP_EXIT_GUARD2]], label [[F]]212; BOOLEAN: E:213; BOOLEAN-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]214; BOOLEAN-NEXT: br label [[H]]215; BOOLEAN: F:216; BOOLEAN-NEXT: [[INNER2]] = add i32 [[INNER1]], 1217; BOOLEAN-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20218; BOOLEAN-NEXT: br i1 [[CMP1]], label [[B]], label [[LOOP_EXIT_GUARD2]]219; BOOLEAN: G:220; BOOLEAN-NEXT: [[OUTER2]] = add i32 [[OUTER1]], 1221; BOOLEAN-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10222; BOOLEAN-NEXT: br i1 [[CMP2]], label [[A]], label [[LOOP_EXIT_GUARD:%.*]]223; BOOLEAN: H:224; BOOLEAN-NEXT: unreachable225; BOOLEAN: I:226; BOOLEAN-NEXT: ret void227; BOOLEAN: loop.exit.guard:228; BOOLEAN-NEXT: [[GUARD_C:%.*]] = phi i1 [ false, [[G]] ], [ [[GUARD_C_MOVED:%.*]], [[LOOP_EXIT_GUARD2]] ]229; BOOLEAN-NEXT: [[GUARD_E:%.*]] = phi i1 [ false, [[G]] ], [ [[GUARD_E_MOVED:%.*]], [[LOOP_EXIT_GUARD2]] ]230; BOOLEAN-NEXT: br i1 [[GUARD_C]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]231; BOOLEAN: loop.exit.guard1:232; BOOLEAN-NEXT: br i1 [[GUARD_E]], label [[E:%.*]], label [[I]]233; BOOLEAN: loop.exit.guard2:234; BOOLEAN-NEXT: [[GUARD_E_MOVED]] = phi i1 [ false, [[B]] ], [ true, [[D]] ], [ poison, [[F]] ]235; BOOLEAN-NEXT: [[GUARD_C_MOVED]] = phi i1 [ true, [[B]] ], [ false, [[D]] ], [ poison, [[F]] ]236; BOOLEAN-NEXT: [[GUARD_LOOP_EXIT_GUARD:%.*]] = phi i1 [ true, [[B]] ], [ true, [[D]] ], [ false, [[F]] ]237; BOOLEAN-NEXT: br i1 [[GUARD_LOOP_EXIT_GUARD]], label [[LOOP_EXIT_GUARD]], label [[G]]238;239entry:240 br i1 %PredEntry, label %A, label %I241 242A:243 %outer1 = phi i32 [ 0, %entry ], [ %outer2, %G ]244 br label %B245 246B:247 %inner1 = phi i32 [ 0, %A ], [ %inner2, %F ]248 br i1 %PredA, label %D, label %C249 250C:251 tail call fastcc void @check(i32 1) #0252 br label %H253 254D:255 br i1 %PredB, label %E, label %F256 257E:258 tail call fastcc void @check(i32 2) #0259 br label %H260 261F:262 %inner2 = add i32 %inner1, 1263 %cmp1 = icmp ult i32 %inner2, 20264 br i1 %cmp1, label %B, label %G265 266G:267 %outer2 = add i32 %outer1, 1268 %cmp2 = icmp ult i32 %outer2, 10269 br i1 %cmp2, label %A, label %I270 271H:272 unreachable273 274I:275 ret void276}277 278define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {279; CHECK-LABEL: @inner_loop_callbr(280; CHECK-NEXT: entry:281; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]282; CHECK: A:283; CHECK-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]284; CHECK-NEXT: br label [[B:%.*]]285; CHECK: B:286; CHECK-NEXT: [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]287; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])288; CHECK-NEXT: to label [[D:%.*]] [label %B.target.B.target.C]289; CHECK: C:290; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]291; CHECK-NEXT: br label [[H:%.*]]292; CHECK: D:293; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])294; CHECK-NEXT: to label [[D_TARGET_D_TARGET_E:%.*]] [label %F]295; CHECK: E:296; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]297; CHECK-NEXT: br label [[H]]298; CHECK: F:299; CHECK-NEXT: [[INNER2]] = add i32 [[INNER1]], 1300; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20301; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[CMP1]])302; CHECK-NEXT: to label [[B]] [label %F.target.G]303; CHECK: G:304; CHECK-NEXT: [[OUTER2]] = add i32 [[OUTER1]], 1305; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10306; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[CMP2]])307; CHECK-NEXT: to label [[A]] [label %G.target.I]308; CHECK: H:309; CHECK-NEXT: unreachable310; CHECK: I:311; CHECK-NEXT: ret void312; CHECK: B.target.C:313; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]314; CHECK: D.target.E:315; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]316; CHECK: G.target.I:317; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]318; CHECK: loop.exit.guard:319; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_E:%.*]] ], [ 2, [[G_TARGET_I:%.*]] ]320; CHECK-NEXT: [[C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0321; CHECK-NEXT: br i1 [[C_PREDICATE]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]322; CHECK: loop.exit.guard1:323; CHECK-NEXT: [[E_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1324; CHECK-NEXT: br i1 [[E_PREDICATE]], label [[E:%.*]], label [[I]]325; CHECK: B.target.B.target.C:326; CHECK-NEXT: br label [[LOOP_EXIT_GUARD2:%.*]]327; CHECK: D.target.D.target.E:328; CHECK-NEXT: br label [[LOOP_EXIT_GUARD2]]329; CHECK: F.target.G:330; CHECK-NEXT: br label [[LOOP_EXIT_GUARD2]]331; CHECK: loop.exit.guard2:332; CHECK-NEXT: [[MERGED_BB_IDX4:%.*]] = phi i32 [ 0, [[B_TARGET_B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_D_TARGET_E]] ], [ 2, [[F_TARGET_G:%.*]] ]333; CHECK-NEXT: [[B_TARGET_C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX4]], 0334; CHECK-NEXT: br i1 [[B_TARGET_C_PREDICATE]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]335; CHECK: loop.exit.guard3:336; CHECK-NEXT: [[D_TARGET_E_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX4]], 1337; CHECK-NEXT: br i1 [[D_TARGET_E_PREDICATE]], label [[D_TARGET_E]], label [[G]]338;339; BOOLEAN-LABEL: @inner_loop_callbr(340; BOOLEAN-NEXT: entry:341; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]342; BOOLEAN: A:343; BOOLEAN-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]344; BOOLEAN-NEXT: br label [[B:%.*]]345; BOOLEAN: B:346; BOOLEAN-NEXT: [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]347; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])348; BOOLEAN-NEXT: to label [[D:%.*]] [label %B.target.B.target.C]349; BOOLEAN: C:350; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]351; BOOLEAN-NEXT: br label [[H:%.*]]352; BOOLEAN: D:353; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])354; BOOLEAN-NEXT: to label [[D_TARGET_D_TARGET_E:%.*]] [label %F]355; BOOLEAN: E:356; BOOLEAN-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]357; BOOLEAN-NEXT: br label [[H]]358; BOOLEAN: F:359; BOOLEAN-NEXT: [[INNER2]] = add i32 [[INNER1]], 1360; BOOLEAN-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20361; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[CMP1]])362; BOOLEAN-NEXT: to label [[B]] [label %F.target.G]363; BOOLEAN: G:364; BOOLEAN-NEXT: [[OUTER2]] = add i32 [[OUTER1]], 1365; BOOLEAN-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10366; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[CMP2]])367; BOOLEAN-NEXT: to label [[A]] [label %G.target.I]368; BOOLEAN: H:369; BOOLEAN-NEXT: unreachable370; BOOLEAN: I:371; BOOLEAN-NEXT: ret void372; BOOLEAN: B.target.C:373; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]374; BOOLEAN: D.target.E:375; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]376; BOOLEAN: G.target.I:377; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]378; BOOLEAN: loop.exit.guard:379; BOOLEAN-NEXT: [[GUARD_C:%.*]] = phi i1 [ true, [[B_TARGET_C:%.*]] ], [ false, [[D_TARGET_E:%.*]] ], [ false, [[G_TARGET_I:%.*]] ]380; BOOLEAN-NEXT: [[GUARD_E:%.*]] = phi i1 [ false, [[B_TARGET_C]] ], [ true, [[D_TARGET_E]] ], [ false, [[G_TARGET_I]] ]381; BOOLEAN-NEXT: br i1 [[GUARD_C]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]382; BOOLEAN: loop.exit.guard1:383; BOOLEAN-NEXT: br i1 [[GUARD_E]], label [[E:%.*]], label [[I]]384; BOOLEAN: B.target.B.target.C:385; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD2:%.*]]386; BOOLEAN: D.target.D.target.E:387; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD2]]388; BOOLEAN: F.target.G:389; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD2]]390; BOOLEAN: loop.exit.guard2:391; BOOLEAN-NEXT: [[GUARD_B_TARGET_C:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_C:%.*]] ], [ false, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G:%.*]] ]392; BOOLEAN-NEXT: [[GUARD_D_TARGET_E:%.*]] = phi i1 [ false, [[B_TARGET_B_TARGET_C]] ], [ true, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G]] ]393; BOOLEAN-NEXT: br i1 [[GUARD_B_TARGET_C]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]394; BOOLEAN: loop.exit.guard3:395; BOOLEAN-NEXT: br i1 [[GUARD_D_TARGET_E]], label [[D_TARGET_E]], label [[G]]396;397entry:398 br i1 %PredEntry, label %A, label %I399 400A:401 %outer1 = phi i32 [ 0, %entry ], [ %outer2, %G ]402 br label %B403 404B:405 %inner1 = phi i32 [ 0, %A ], [ %inner2, %F ]406 callbr void asm "", "r,!i"(i1 %PredA) to label %D [label %C]407 408C:409 tail call fastcc void @check(i32 1) #0410 br label %H411 412D:413 callbr void asm "", "r,!i"(i1 %PredB) to label %E [label %F]414 415E:416 tail call fastcc void @check(i32 2) #0417 br label %H418 419F:420 %inner2 = add i32 %inner1, 1421 %cmp1 = icmp ult i32 %inner2, 20422 callbr void asm "", "r,!i"(i1 %cmp1) to label %B [label %G]423 424G:425 %outer2 = add i32 %outer1, 1426 %cmp2 = icmp ult i32 %outer2, 10427 callbr void asm "", "r,!i"(i1 %cmp2) to label %A [label %I]428 429H:430 unreachable431 432I:433 ret void434}435 436; A loop with more exit blocks.437 438define void @loop_five_exits(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredD) {439; CHECK-LABEL: @loop_five_exits(440; CHECK-NEXT: entry:441; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[L:%.*]]442; CHECK: A:443; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]444; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[LOOP_EXIT_GUARD:%.*]], label [[C:%.*]]445; CHECK: B:446; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]447; CHECK-NEXT: br label [[J:%.*]]448; CHECK: C:449; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[LOOP_EXIT_GUARD]], label [[E:%.*]]450; CHECK: D:451; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]452; CHECK-NEXT: br label [[J]]453; CHECK: E:454; CHECK-NEXT: br i1 [[PREDC:%.*]], label [[LOOP_EXIT_GUARD]], label [[G:%.*]]455; CHECK: F:456; CHECK-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]457; CHECK-NEXT: br label [[K:%.*]]458; CHECK: G:459; CHECK-NEXT: br i1 [[PREDD:%.*]], label [[LOOP_EXIT_GUARD]], label [[I]]460; CHECK: H:461; CHECK-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]462; CHECK-NEXT: br label [[K]]463; CHECK: I:464; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1465; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10466; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]467; CHECK: J:468; CHECK-NEXT: br label [[L]]469; CHECK: K:470; CHECK-NEXT: br label [[L]]471; CHECK: L:472; CHECK-NEXT: ret void473; CHECK: loop.exit.guard:474; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A]] ], [ 1, [[C]] ], [ 2, [[E]] ], [ 3, [[G]] ], [ 4, [[I]] ]475; CHECK-NEXT: [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0476; CHECK-NEXT: br i1 [[B_PREDICATE]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]477; CHECK: loop.exit.guard1:478; CHECK-NEXT: [[D_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1479; CHECK-NEXT: br i1 [[D_PREDICATE]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]480; CHECK: loop.exit.guard2:481; CHECK-NEXT: [[F_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 2482; CHECK-NEXT: br i1 [[F_PREDICATE]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]483; CHECK: loop.exit.guard3:484; CHECK-NEXT: [[H_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 3485; CHECK-NEXT: br i1 [[H_PREDICATE]], label [[H:%.*]], label [[L]]486;487; BOOLEAN-LABEL: @loop_five_exits(488; BOOLEAN-NEXT: entry:489; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[L:%.*]]490; BOOLEAN: A:491; BOOLEAN-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]492; BOOLEAN-NEXT: br i1 [[PREDA:%.*]], label [[LOOP_EXIT_GUARD:%.*]], label [[C:%.*]]493; BOOLEAN: B:494; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]495; BOOLEAN-NEXT: br label [[J:%.*]]496; BOOLEAN: C:497; BOOLEAN-NEXT: br i1 [[PREDB:%.*]], label [[LOOP_EXIT_GUARD]], label [[E:%.*]]498; BOOLEAN: D:499; BOOLEAN-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]500; BOOLEAN-NEXT: br label [[J]]501; BOOLEAN: E:502; BOOLEAN-NEXT: br i1 [[PREDC:%.*]], label [[LOOP_EXIT_GUARD]], label [[G:%.*]]503; BOOLEAN: F:504; BOOLEAN-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]505; BOOLEAN-NEXT: br label [[K:%.*]]506; BOOLEAN: G:507; BOOLEAN-NEXT: br i1 [[PREDD:%.*]], label [[LOOP_EXIT_GUARD]], label [[I]]508; BOOLEAN: H:509; BOOLEAN-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]510; BOOLEAN-NEXT: br label [[K]]511; BOOLEAN: I:512; BOOLEAN-NEXT: [[INC2]] = add i32 [[INC1]], 1513; BOOLEAN-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10514; BOOLEAN-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]515; BOOLEAN: J:516; BOOLEAN-NEXT: br label [[L]]517; BOOLEAN: K:518; BOOLEAN-NEXT: br label [[L]]519; BOOLEAN: L:520; BOOLEAN-NEXT: ret void521; BOOLEAN: loop.exit.guard:522; BOOLEAN-NEXT: [[GUARD_B:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ], [ false, [[E]] ], [ false, [[G]] ], [ false, [[I]] ]523; BOOLEAN-NEXT: [[GUARD_D:%.*]] = phi i1 [ false, [[A]] ], [ true, [[C]] ], [ false, [[E]] ], [ false, [[G]] ], [ false, [[I]] ]524; BOOLEAN-NEXT: [[GUARD_F:%.*]] = phi i1 [ false, [[A]] ], [ false, [[C]] ], [ true, [[E]] ], [ false, [[G]] ], [ false, [[I]] ]525; BOOLEAN-NEXT: [[GUARD_H:%.*]] = phi i1 [ false, [[A]] ], [ false, [[C]] ], [ false, [[E]] ], [ true, [[G]] ], [ false, [[I]] ]526; BOOLEAN-NEXT: br i1 [[GUARD_B]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]527; BOOLEAN: loop.exit.guard1:528; BOOLEAN-NEXT: br i1 [[GUARD_D]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]529; BOOLEAN: loop.exit.guard2:530; BOOLEAN-NEXT: br i1 [[GUARD_F]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]531; BOOLEAN: loop.exit.guard3:532; BOOLEAN-NEXT: br i1 [[GUARD_H]], label [[H:%.*]], label [[L]]533;534entry:535 br i1 %PredEntry, label %A, label %L536 537A:538 %inc1 = phi i32 [ 0, %entry ], [ %inc2, %I ]539 br i1 %PredA, label %B, label %C540 541B:542 tail call fastcc void @check(i32 1) #0543 br label %J544 545C:546 br i1 %PredB, label %D, label %E547 548D:549 tail call fastcc void @check(i32 2) #0550 br label %J551 552E:553 br i1 %PredC, label %F, label %G554 555F:556 tail call fastcc void @check(i32 3) #0557 br label %K558 559G:560 br i1 %PredD, label %H, label %I561 562H:563 tail call fastcc void @check(i32 4) #0564 br label %K565 566I:567 %inc2 = add i32 %inc1, 1568 %cmp = icmp ult i32 %inc2, 10569 br i1 %cmp, label %A, label %L570 571J:572 br label %L573 574K:575 br label %L576 577L:578 ret void579}580 581define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredD) {582; CHECK-LABEL: @loop_five_exits_callbr(583; CHECK-NEXT: entry:584; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[L:%.*]]585; CHECK: A:586; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]587; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])588; CHECK-NEXT: to label [[A_TARGET_B:%.*]] [label %C]589; CHECK: B:590; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]591; CHECK-NEXT: br label [[J:%.*]]592; CHECK: C:593; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])594; CHECK-NEXT: to label [[C_TARGET_D:%.*]] [label %E]595; CHECK: D:596; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]597; CHECK-NEXT: br label [[J]]598; CHECK: E:599; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])600; CHECK-NEXT: to label [[E_TARGET_F:%.*]] [label %G]601; CHECK: F:602; CHECK-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]603; CHECK-NEXT: br label [[K:%.*]]604; CHECK: G:605; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDD:%.*]])606; CHECK-NEXT: to label [[G_TARGET_H:%.*]] [label %I]607; CHECK: H:608; CHECK-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]609; CHECK-NEXT: br label [[K]]610; CHECK: I:611; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1612; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10613; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[CMP]])614; CHECK-NEXT: to label [[A]] [label %I.target.L]615; CHECK: J:616; CHECK-NEXT: br label [[L]]617; CHECK: K:618; CHECK-NEXT: br label [[L]]619; CHECK: L:620; CHECK-NEXT: ret void621; CHECK: A.target.B:622; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]623; CHECK: C.target.D:624; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]625; CHECK: E.target.F:626; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]627; CHECK: G.target.H:628; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]629; CHECK: I.target.L:630; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]631; CHECK: loop.exit.guard:632; CHECK-NEXT: [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_D]] ], [ 2, [[E_TARGET_F]] ], [ 3, [[G_TARGET_H]] ], [ 4, [[I_TARGET_L:%.*]] ]633; CHECK-NEXT: [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0634; CHECK-NEXT: br i1 [[B_PREDICATE]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]635; CHECK: loop.exit.guard1:636; CHECK-NEXT: [[D_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1637; CHECK-NEXT: br i1 [[D_PREDICATE]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]638; CHECK: loop.exit.guard2:639; CHECK-NEXT: [[F_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 2640; CHECK-NEXT: br i1 [[F_PREDICATE]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]641; CHECK: loop.exit.guard3:642; CHECK-NEXT: [[H_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 3643; CHECK-NEXT: br i1 [[H_PREDICATE]], label [[H:%.*]], label [[L]]644;645; BOOLEAN-LABEL: @loop_five_exits_callbr(646; BOOLEAN-NEXT: entry:647; BOOLEAN-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[L:%.*]]648; BOOLEAN: A:649; BOOLEAN-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]650; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])651; BOOLEAN-NEXT: to label [[A_TARGET_B:%.*]] [label %C]652; BOOLEAN: B:653; BOOLEAN-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]654; BOOLEAN-NEXT: br label [[J:%.*]]655; BOOLEAN: C:656; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])657; BOOLEAN-NEXT: to label [[C_TARGET_D:%.*]] [label %E]658; BOOLEAN: D:659; BOOLEAN-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]660; BOOLEAN-NEXT: br label [[J]]661; BOOLEAN: E:662; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])663; BOOLEAN-NEXT: to label [[E_TARGET_F:%.*]] [label %G]664; BOOLEAN: F:665; BOOLEAN-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]666; BOOLEAN-NEXT: br label [[K:%.*]]667; BOOLEAN: G:668; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[PREDD:%.*]])669; BOOLEAN-NEXT: to label [[G_TARGET_H:%.*]] [label %I]670; BOOLEAN: H:671; BOOLEAN-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]672; BOOLEAN-NEXT: br label [[K]]673; BOOLEAN: I:674; BOOLEAN-NEXT: [[INC2]] = add i32 [[INC1]], 1675; BOOLEAN-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10676; BOOLEAN-NEXT: callbr void asm "", "r,!i"(i1 [[CMP]])677; BOOLEAN-NEXT: to label [[A]] [label %I.target.L]678; BOOLEAN: J:679; BOOLEAN-NEXT: br label [[L]]680; BOOLEAN: K:681; BOOLEAN-NEXT: br label [[L]]682; BOOLEAN: L:683; BOOLEAN-NEXT: ret void684; BOOLEAN: A.target.B:685; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]686; BOOLEAN: C.target.D:687; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]688; BOOLEAN: E.target.F:689; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]690; BOOLEAN: G.target.H:691; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]692; BOOLEAN: I.target.L:693; BOOLEAN-NEXT: br label [[LOOP_EXIT_GUARD]]694; BOOLEAN: loop.exit.guard:695; BOOLEAN-NEXT: [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L:%.*]] ]696; BOOLEAN-NEXT: [[GUARD_D:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ true, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]697; BOOLEAN-NEXT: [[GUARD_F:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ true, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]698; BOOLEAN-NEXT: [[GUARD_H:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ true, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]699; BOOLEAN-NEXT: br i1 [[GUARD_B]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]700; BOOLEAN: loop.exit.guard1:701; BOOLEAN-NEXT: br i1 [[GUARD_D]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]702; BOOLEAN: loop.exit.guard2:703; BOOLEAN-NEXT: br i1 [[GUARD_F]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]704; BOOLEAN: loop.exit.guard3:705; BOOLEAN-NEXT: br i1 [[GUARD_H]], label [[H:%.*]], label [[L]]706;707entry:708 br i1 %PredEntry, label %A, label %L709 710A:711 %inc1 = phi i32 [ 0, %entry ], [ %inc2, %I ]712 callbr void asm "", "r,!i"(i1 %PredA) to label %B [label %C]713 714B:715 tail call fastcc void @check(i32 1) #0716 br label %J717 718C:719 callbr void asm "", "r,!i"(i1 %PredB) to label %D [label %E]720 721D:722 tail call fastcc void @check(i32 2) #0723 br label %J724 725E:726 callbr void asm "", "r,!i"(i1 %PredC) to label %F [label %G]727 728F:729 tail call fastcc void @check(i32 3) #0730 br label %K731 732G:733 callbr void asm "", "r,!i"(i1 %PredD) to label %H [label %I]734 735H:736 tail call fastcc void @check(i32 4) #0737 br label %K738 739I:740 %inc2 = add i32 %inc1, 1741 %cmp = icmp ult i32 %inc2, 10742 callbr void asm "", "r,!i"(i1 %cmp) to label %A [label %L]743 744J:745 br label %L746 747K:748 br label %L749 750L:751 ret void752}753 754 755declare void @check(i32 noundef %i) #0756 757attributes #0 = { noreturn nounwind }758 759