2365 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -freeze-loop-unswitch-cond -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s3; RUN: opt -freeze-loop-unswitch-cond -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S -verify-memoryssa < %s | FileCheck %s4 5declare i32 @a()6declare i32 @b()7declare i32 @c()8declare i32 @d()9 10declare void @sink1(i32)11declare void @sink2(i32)12declare void @sink3(i1)13declare void @sink4(i1)14 15declare i1 @cond()16declare i32 @cond.i32()17 18declare i32 @__CxxFrameHandler3(...)19 20define i32 @test1_freeze(ptr %ptr0, ptr %ptr1, ptr %ptr2) {21; CHECK-LABEL: @test1_freeze(22; CHECK-NEXT: entry:23; CHECK-NEXT: [[COND1:%.*]] = load i1, ptr [[PTR1:%.*]], align 124; CHECK-NEXT: [[COND2:%.*]] = load i1, ptr [[PTR2:%.*]], align 125; CHECK-NEXT: br i1 [[COND1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]26; CHECK: entry.split.us:27; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]28; CHECK: loop_begin.us:29; CHECK-NEXT: br label [[LOOP_A_US:%.*]]30; CHECK: loop_a.us:31; CHECK-NEXT: [[TMP0:%.*]] = call i32 @a()32; CHECK-NEXT: br label [[LATCH_US:%.*]]33; CHECK: latch.us:34; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR0:%.*]], align 135; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]36; CHECK: loop_exit.split.us:37; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]38; CHECK: entry.split:39; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2]]40; CHECK-NEXT: br i1 [[COND2_FR]], label [[ENTRY_SPLIT_SPLIT_US:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]41; CHECK: entry.split.split.us:42; CHECK-NEXT: br label [[LOOP_BEGIN_US1:%.*]]43; CHECK: loop_begin.us1:44; CHECK-NEXT: br label [[LOOP_B_US:%.*]]45; CHECK: loop_b.us:46; CHECK-NEXT: [[TMP1:%.*]] = call i32 @b()47; CHECK-NEXT: br label [[LOOP_B_A_US:%.*]]48; CHECK: loop_b_a.us:49; CHECK-NEXT: call void @sink3(i1 true)50; CHECK-NEXT: br label [[LATCH_US2:%.*]]51; CHECK: latch.us2:52; CHECK-NEXT: [[V_US3:%.*]] = load i1, ptr [[PTR0]], align 153; CHECK-NEXT: br i1 [[V_US3]], label [[LOOP_BEGIN_US1]], label [[LOOP_EXIT_SPLIT_SPLIT_US:%.*]]54; CHECK: loop_exit.split.split.us:55; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]56; CHECK: entry.split.split:57; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]58; CHECK: loop_begin:59; CHECK-NEXT: br label [[LOOP_B:%.*]]60; CHECK: loop_b:61; CHECK-NEXT: [[TMP2:%.*]] = call i32 @b()62; CHECK-NEXT: br label [[LOOP_B_B:%.*]]63; CHECK: loop_b_b:64; CHECK-NEXT: call void @sink4(i1 false)65; CHECK-NEXT: br label [[LATCH:%.*]]66; CHECK: latch:67; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR0]], align 168; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT_SPLIT:%.*]]69; CHECK: loop_exit.split.split:70; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]71; CHECK: loop_exit.split:72; CHECK-NEXT: br label [[LOOP_EXIT]]73; CHECK: loop_exit:74; CHECK-NEXT: ret i32 075;76entry:77 %cond1 = load i1, ptr %ptr178 %cond2 = load i1, ptr %ptr279 br label %loop_begin80 81loop_begin:82 br i1 %cond1, label %loop_a, label %loop_b83 84loop_a:85 call i32 @a()86 br label %latch87; The 'loop_a' unswitched loop.88 89loop_b:90 call i32 @b()91 br i1 %cond2, label %loop_b_a, label %loop_b_b92; The second unswitched condition.93 94loop_b_a:95 call void @sink3(i1 %cond2)96 br label %latch97; The 'loop_b_a' unswitched loop.98; %cond2 is replaced to true99 100loop_b_b:101 call void @sink4(i1 %cond2)102 br label %latch103; The 'loop_b_b' unswitched loop.104; %cond2 is replaced to false105 106latch:107 %v = load i1, ptr %ptr0108 br i1 %v, label %loop_begin, label %loop_exit109 110loop_exit:111 ret i32 0112}113 114; Test that when unswitching a deeply nested loop condition in a way that115; produces a non-loop clone that can reach multiple exit blocks which are part116; of different outer loops we correctly divide the cloned loop blocks between117; the outer loops based on reachability.118define i32 @test7a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {119; CHECK-LABEL: @test7a(120; CHECK-NEXT: entry:121; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]122; CHECK: loop_begin:123; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4124; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]125; CHECK: inner_loop_begin:126; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]127; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1128; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4129; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]130; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]131; CHECK: inner_loop_begin.split.us:132; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]133; CHECK: inner_inner_loop_begin.us:134; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1135; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]136; CHECK: inner_inner_loop_b.us:137; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1138; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US_LOOPEXIT:%.*]]139; CHECK: inner_inner_loop_a.us:140; CHECK-NEXT: [[A_PHI_LCSSA10:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN_US]] ]141; CHECK-NEXT: [[B_LCSSA6:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN_US]] ]142; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1143; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]144; CHECK: inner_inner_loop_c.us.loopexit:145; CHECK-NEXT: br label [[INNER_INNER_LOOP_C_US]]146; CHECK: inner_inner_loop_c.us:147; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1148; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]149; CHECK: inner_inner_loop_d.us:150; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]]151; CHECK: inner_inner_loop_exit.split.us:152; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]153; CHECK: loop_exit.split.us:154; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI_LCSSA10]], [[INNER_INNER_LOOP_A_US]] ]155; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B_LCSSA6]], [[INNER_INNER_LOOP_A_US]] ]156; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]157; CHECK: inner_loop_exit.loopexit.split.us:158; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]159; CHECK: inner_loop_begin.split:160; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]161; CHECK: inner_inner_loop_begin:162; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1163; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]164; CHECK: inner_inner_loop_a:165; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1166; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]167; CHECK: inner_inner_loop_b:168; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1169; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C]]170; CHECK: inner_inner_loop_c:171; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1172; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]173; CHECK: inner_inner_loop_d:174; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]175; CHECK: inner_inner_loop_exit.split:176; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]177; CHECK: inner_inner_loop_exit:178; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4179; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1180; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]181; CHECK: inner_loop_exit.loopexit.split:182; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]183; CHECK: inner_loop_exit.loopexit:184; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]185; CHECK: inner_loop_exit.loopexit1:186; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]187; CHECK: inner_loop_exit:188; CHECK-NEXT: br label [[LOOP_BEGIN]]189; CHECK: loop_exit.split:190; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]191; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A]] ]192; CHECK-NEXT: br label [[LOOP_EXIT]]193; CHECK: loop_exit:194; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]195; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]196; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]197; CHECK-NEXT: ret i32 [[RESULT]]198;199entry:200 br label %loop_begin201 202loop_begin:203 %a = load i32, ptr %a.ptr204 br label %inner_loop_begin205 206inner_loop_begin:207 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]208 %cond = load i1, ptr %cond.ptr209 %b = load i32, ptr %b.ptr210 br label %inner_inner_loop_begin211 212inner_inner_loop_begin:213 %v1 = load i1, ptr %ptr214 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b215 216inner_inner_loop_a:217 %v2 = load i1, ptr %ptr218 br i1 %v2, label %loop_exit, label %inner_inner_loop_c219 220inner_inner_loop_b:221 %v3 = load i1, ptr %ptr222 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c223 224inner_inner_loop_c:225 %v4 = load i1, ptr %ptr226 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d227 228inner_inner_loop_d:229 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_begin230; The cloned copy that always exits with the adjustments required to fix up231; loop exits.232; The original copy that continues to loop.233 234inner_inner_loop_exit:235 %a2 = load i32, ptr %a.ptr236 %v5 = load i1, ptr %ptr237 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin238 239inner_loop_exit:240 br label %loop_begin241 242loop_exit:243 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]244 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]245 %result = add i32 %a.lcssa, %b.lcssa246 ret i32 %result247}248 249; Same pattern as @test7a but here the original loop becomes a non-loop that250; can reach multiple exit blocks which are part of different outer loops.251define i32 @test7b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {252; CHECK-LABEL: @test7b(253; CHECK-NEXT: entry:254; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]255; CHECK: loop_begin:256; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4257; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]258; CHECK: inner_loop_begin:259; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]260; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1261; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4262; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]263; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]264; CHECK: inner_loop_begin.split.us:265; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]266; CHECK: inner_inner_loop_begin.us:267; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1268; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]269; CHECK: inner_inner_loop_b.us:270; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1271; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]272; CHECK: inner_inner_loop_a.us:273; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1274; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US]]275; CHECK: inner_inner_loop_c.us:276; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1277; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]278; CHECK: inner_inner_loop_d.us:279; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]280; CHECK: inner_inner_loop_exit.split.us:281; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]282; CHECK: loop_exit.split.us:283; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]284; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A_US]] ]285; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]286; CHECK: inner_loop_exit.loopexit.split.us:287; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]288; CHECK: inner_loop_begin.split:289; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]290; CHECK: inner_inner_loop_begin:291; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1292; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]293; CHECK: inner_inner_loop_a:294; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN]] ]295; CHECK-NEXT: [[B_LCSSA3:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN]] ]296; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1297; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]298; CHECK: inner_inner_loop_b:299; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1300; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C_LOOPEXIT:%.*]]301; CHECK: inner_inner_loop_c.loopexit:302; CHECK-NEXT: br label [[INNER_INNER_LOOP_C]]303; CHECK: inner_inner_loop_c:304; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1305; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]306; CHECK: inner_inner_loop_d:307; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]]308; CHECK: inner_inner_loop_exit.split:309; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]310; CHECK: inner_inner_loop_exit:311; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4312; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1313; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]314; CHECK: inner_loop_exit.loopexit.split:315; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]316; CHECK: inner_loop_exit.loopexit:317; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]318; CHECK: inner_loop_exit.loopexit1:319; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]320; CHECK: inner_loop_exit:321; CHECK-NEXT: br label [[LOOP_BEGIN]]322; CHECK: loop_exit.split:323; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_INNER_LOOP_A]] ]324; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B_LCSSA3]], [[INNER_INNER_LOOP_A]] ]325; CHECK-NEXT: br label [[LOOP_EXIT]]326; CHECK: loop_exit:327; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]328; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]329; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]330; CHECK-NEXT: ret i32 [[RESULT]]331;332entry:333 br label %loop_begin334 335loop_begin:336 %a = load i32, ptr %a.ptr337 br label %inner_loop_begin338 339inner_loop_begin:340 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]341 %cond = load i1, ptr %cond.ptr342 %b = load i32, ptr %b.ptr343 br label %inner_inner_loop_begin344 345inner_inner_loop_begin:346 %v1 = load i1, ptr %ptr347 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b348 349inner_inner_loop_a:350 %v2 = load i1, ptr %ptr351 br i1 %v2, label %loop_exit, label %inner_inner_loop_c352 353inner_inner_loop_b:354 %v3 = load i1, ptr %ptr355 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c356 357inner_inner_loop_c:358 %v4 = load i1, ptr %ptr359 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d360 361inner_inner_loop_d:362 br i1 %cond, label %inner_inner_loop_begin, label %inner_loop_exit363; The cloned copy that continues looping.364; The original copy that now always exits and needs adjustments for exit365; blocks.366 367inner_inner_loop_exit:368 %a2 = load i32, ptr %a.ptr369 %v5 = load i1, ptr %ptr370 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin371 372inner_loop_exit:373 br label %loop_begin374 375loop_exit:376 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]377 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]378 %result = add i32 %a.lcssa, %b.lcssa379 ret i32 %result380}381 382; Test that when the exit block set of an inner loop changes to start at a less383; high level of the loop nest we correctly hoist the loop up the nest.384define i32 @test8a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {385; CHECK-LABEL: @test8a(386; CHECK-NEXT: entry:387; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]388; CHECK: loop_begin:389; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4390; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]391; CHECK: inner_loop_begin:392; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]393; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1394; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4395; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]396; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]397; CHECK: inner_loop_begin.split.us:398; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]399; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]400; CHECK: inner_inner_loop_begin.us:401; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1402; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]403; CHECK: inner_inner_loop_b.us:404; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH_US:%.*]]405; CHECK: inner_inner_loop_a.us:406; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1407; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]408; CHECK: inner_inner_loop_latch.us:409; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]410; CHECK: inner_loop_exit.loopexit.split.us:411; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A_US]] ]412; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]413; CHECK: inner_loop_begin.split:414; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]415; CHECK: inner_inner_loop_begin:416; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1417; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]418; CHECK: inner_inner_loop_a:419; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1420; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]421; CHECK: inner_inner_loop_b:422; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]423; CHECK: inner_inner_loop_latch:424; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]425; CHECK: inner_inner_loop_exit:426; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4427; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1428; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]429; CHECK: inner_loop_exit.loopexit.split:430; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]431; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]432; CHECK: inner_loop_exit.loopexit:433; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]434; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]435; CHECK: inner_loop_exit.loopexit1:436; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]437; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]438; CHECK: inner_loop_exit:439; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]440; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1441; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]442; CHECK: loop_exit:443; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]444; CHECK-NEXT: ret i32 [[A_LCSSA]]445;446entry:447 br label %loop_begin448 449loop_begin:450 %a = load i32, ptr %a.ptr451 br label %inner_loop_begin452 453inner_loop_begin:454 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]455 %cond = load i1, ptr %cond.ptr456 %b = load i32, ptr %b.ptr457 br label %inner_inner_loop_begin458 459inner_inner_loop_begin:460 %v1 = load i1, ptr %ptr461 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b462 463inner_inner_loop_a:464 %v2 = load i1, ptr %ptr465 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit466 467inner_inner_loop_b:468 br i1 %cond, label %inner_inner_loop_latch, label %inner_inner_loop_exit469 470inner_inner_loop_latch:471 br label %inner_inner_loop_begin472; The cloned region is now an exit from the inner loop.473; The original region exits the loop earlier.474 475inner_inner_loop_exit:476 %a2 = load i32, ptr %a.ptr477 %v4 = load i1, ptr %ptr478 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin479 480inner_loop_exit:481 %v5 = load i1, ptr %ptr482 br i1 %v5, label %loop_exit, label %loop_begin483 484loop_exit:485 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]486 ret i32 %a.lcssa487}488 489; Same pattern as @test8a but where the original loop looses an exit block and490; needs to be hoisted up the nest.491define i32 @test8b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {492; CHECK-LABEL: @test8b(493; CHECK-NEXT: entry:494; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]495; CHECK: loop_begin:496; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4497; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]498; CHECK: inner_loop_begin:499; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]500; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1501; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4502; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]503; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]504; CHECK: inner_loop_begin.split.us:505; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]506; CHECK: inner_inner_loop_begin.us:507; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1508; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]509; CHECK: inner_inner_loop_b.us:510; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]]511; CHECK: inner_inner_loop_a.us:512; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1513; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]514; CHECK: inner_inner_loop_latch.us:515; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]516; CHECK: inner_inner_loop_exit.split.us:517; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]518; CHECK: inner_loop_exit.loopexit.split.us:519; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]520; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]521; CHECK: inner_loop_begin.split:522; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]523; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]524; CHECK: inner_inner_loop_begin:525; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1526; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]527; CHECK: inner_inner_loop_a:528; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1529; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]530; CHECK: inner_inner_loop_b:531; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH]]532; CHECK: inner_inner_loop_latch:533; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]534; CHECK: inner_inner_loop_exit:535; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4536; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1537; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]538; CHECK: inner_loop_exit.loopexit.split:539; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A]] ]540; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]541; CHECK: inner_loop_exit.loopexit:542; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]543; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]544; CHECK: inner_loop_exit.loopexit1:545; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]546; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]547; CHECK: inner_loop_exit:548; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]549; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1550; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]551; CHECK: loop_exit:552; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]553; CHECK-NEXT: ret i32 [[A_LCSSA]]554;555entry:556 br label %loop_begin557 558loop_begin:559 %a = load i32, ptr %a.ptr560 br label %inner_loop_begin561 562inner_loop_begin:563 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]564 %cond = load i1, ptr %cond.ptr565 %b = load i32, ptr %b.ptr566 br label %inner_inner_loop_begin567 568inner_inner_loop_begin:569 %v1 = load i1, ptr %ptr570 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b571 572inner_inner_loop_a:573 %v2 = load i1, ptr %ptr574 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit575 576inner_inner_loop_b:577 br i1 %cond, label %inner_inner_loop_exit, label %inner_inner_loop_latch578 579inner_inner_loop_latch:580 br label %inner_inner_loop_begin581; The cloned region is similar to before but with one earlier exit.582; The original region is now an exit in the preheader.583 584inner_inner_loop_exit:585 %a2 = load i32, ptr %a.ptr586 %v4 = load i1, ptr %ptr587 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin588 589inner_loop_exit:590 %v5 = load i1, ptr %ptr591 br i1 %v5, label %loop_exit, label %loop_begin592 593loop_exit:594 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]595 ret i32 %a.lcssa596}597 598; Test that requires re-forming dedicated exits for the cloned loop.599define i32 @test10a(ptr %ptr, i1 %cond, ptr %a.ptr) {600; CHECK-LABEL: @test10a(601; CHECK-NEXT: entry:602; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]603; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]604; CHECK: entry.split.us:605; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]606; CHECK: loop_begin.us:607; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4608; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1609; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]610; CHECK: loop_b.us:611; CHECK-NEXT: [[A_US_LCSSA:%.*]] = phi i32 [ [[A_US]], [[LOOP_BEGIN_US]] ]612; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]613; CHECK: loop_a.us:614; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1615; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_BEGIN_BACKEDGE_US:%.*]]616; CHECK: loop_begin.backedge.us:617; CHECK-NEXT: br label [[LOOP_BEGIN_US]]618; CHECK: loop_exit.split.us.loopexit:619; CHECK-NEXT: [[A_LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]620; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]621; CHECK: loop_exit.split.us:622; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US_LCSSA]], [[LOOP_B_US]] ], [ [[A_LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]623; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]624; CHECK: entry.split:625; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]626; CHECK: loop_begin:627; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4628; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1629; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]630; CHECK: loop_a:631; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1632; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_BEGIN_BACKEDGE:%.*]]633; CHECK: loop_begin.backedge:634; CHECK-NEXT: br label [[LOOP_BEGIN]]635; CHECK: loop_b:636; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE]]637; CHECK: loop_exit.split:638; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]639; CHECK-NEXT: br label [[LOOP_EXIT]]640; CHECK: loop_exit:641; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]642; CHECK-NEXT: ret i32 [[DOTUS_PHI]]643;644entry:645 br label %loop_begin646 647loop_begin:648 %a = load i32, ptr %a.ptr649 %v1 = load i1, ptr %ptr650 br i1 %v1, label %loop_a, label %loop_b651 652loop_a:653 %v2 = load i1, ptr %ptr654 br i1 %v2, label %loop_exit, label %loop_begin655 656loop_b:657 br i1 %cond, label %loop_exit, label %loop_begin658; The cloned loop with one edge as a direct exit.659 660; The original loop without one 'loop_exit' edge.661 662loop_exit:663 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]664 ret i32 %a.lcssa665}666 667; Test that requires re-forming dedicated exits for the original loop.668define i32 @test10b(ptr %ptr, i1 %cond, ptr %a.ptr) {669; CHECK-LABEL: @test10b(670; CHECK-NEXT: entry:671; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]672; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]673; CHECK: entry.split.us:674; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]675; CHECK: loop_begin.us:676; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4677; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1678; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]679; CHECK: loop_b.us:680; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE_US:%.*]]681; CHECK: loop_a.us:682; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1683; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_BEGIN_BACKEDGE_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]684; CHECK: loop_begin.backedge.us:685; CHECK-NEXT: br label [[LOOP_BEGIN_US]]686; CHECK: loop_exit.split.us:687; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]688; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]689; CHECK: entry.split:690; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]691; CHECK: loop_begin:692; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4693; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1694; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]695; CHECK: loop_a:696; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1697; CHECK-NEXT: br i1 [[V2]], label [[LOOP_BEGIN_BACKEDGE:%.*]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]]698; CHECK: loop_begin.backedge:699; CHECK-NEXT: br label [[LOOP_BEGIN]]700; CHECK: loop_b:701; CHECK-NEXT: [[A_LCSSA1:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ]702; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]703; CHECK: loop_exit.split.loopexit:704; CHECK-NEXT: [[A_LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]705; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]706; CHECK: loop_exit.split:707; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA1]], [[LOOP_B]] ], [ [[A_LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]708; CHECK-NEXT: br label [[LOOP_EXIT]]709; CHECK: loop_exit:710; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]711; CHECK-NEXT: ret i32 [[DOTUS_PHI]]712;713entry:714 br label %loop_begin715 716loop_begin:717 %a = load i32, ptr %a.ptr718 %v1 = load i1, ptr %ptr719 br i1 %v1, label %loop_a, label %loop_b720 721loop_a:722 %v2 = load i1, ptr %ptr723 br i1 %v2, label %loop_begin, label %loop_exit724 725loop_b:726 br i1 %cond, label %loop_begin, label %loop_exit727; The cloned loop without one of the exits.728 729; The original loop without one 'loop_exit' edge.730 731loop_exit:732 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]733 ret i32 %a.lcssa734}735 736; Check that if a cloned inner loop after unswitching doesn't loop and directly737; exits even an outer loop, we don't add the cloned preheader to the outer738; loop and do add the needed LCSSA phi nodes for the new exit block from the739; outer loop.740define i32 @test11a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {741; CHECK-LABEL: @test11a(742; CHECK-NEXT: entry:743; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]744; CHECK: loop_begin:745; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4746; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1747; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]748; CHECK: inner_loop_ph:749; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1750; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]751; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]752; CHECK: inner_loop_ph.split.us:753; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]754; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]755; CHECK: inner_loop_begin.us:756; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])757; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4758; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]759; CHECK: loop_exit.loopexit.split.us:760; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_BEGIN_US]] ]761; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]762; CHECK: inner_loop_ph.split:763; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]764; CHECK: inner_loop_begin:765; CHECK-NEXT: call void @sink1(i32 [[B]])766; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4767; CHECK-NEXT: br label [[INNER_LOOP_A:%.*]]768; CHECK: inner_loop_a:769; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1770; CHECK-NEXT: br i1 [[V2]], label [[INNER_LOOP_EXIT:%.*]], label [[INNER_LOOP_BEGIN]]771; CHECK: inner_loop_exit:772; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_A]] ]773; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1774; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]775; CHECK: loop_latch:776; CHECK-NEXT: br label [[LOOP_BEGIN]]777; CHECK: loop_exit.loopexit:778; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]779; CHECK: loop_exit.loopexit1:780; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]781; CHECK-NEXT: br label [[LOOP_EXIT]]782; CHECK: loop_exit:783; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]784; CHECK-NEXT: ret i32 [[A_LCSSA]]785;786entry:787 br label %loop_begin788 789loop_begin:790 %b = load i32, ptr %b.ptr791 %v1 = load i1, ptr %ptr792 br i1 %v1, label %loop_latch, label %inner_loop_ph793 794inner_loop_ph:795 %cond = load i1, ptr %cond.ptr796 br label %inner_loop_begin797 798inner_loop_begin:799 call void @sink1(i32 %b)800 %a = load i32, ptr %a.ptr801 br i1 %cond, label %loop_exit, label %inner_loop_a802 803inner_loop_a:804 %v2 = load i1, ptr %ptr805 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin806; The cloned path doesn't actually loop and is an exit from the outer loop as807; well.808; The original remains a loop losing the exit edge.809 810inner_loop_exit:811 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]812 %v3 = load i1, ptr %ptr813 br i1 %v3, label %loop_latch, label %loop_exit814 815loop_latch:816 br label %loop_begin817 818loop_exit:819 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]820 ret i32 %a.lcssa821}822 823; Check that if the original inner loop after unswitching doesn't loop and824; directly exits even an outer loop, we remove the original preheader from the825; outer loop and add needed LCSSA phi nodes for the new exit block from the826; outer loop.827define i32 @test11b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {828; CHECK-LABEL: @test11b(829; CHECK-NEXT: entry:830; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]831; CHECK: loop_begin:832; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4833; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1834; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]835; CHECK: inner_loop_ph:836; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1837; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]838; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]839; CHECK: inner_loop_ph.split.us:840; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]841; CHECK: inner_loop_begin.us:842; CHECK-NEXT: call void @sink1(i32 [[B]])843; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4844; CHECK-NEXT: br label [[INNER_LOOP_A_US:%.*]]845; CHECK: inner_loop_a.us:846; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1847; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_US]]848; CHECK: inner_loop_exit.split.us:849; CHECK-NEXT: [[A_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_A_US]] ]850; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]851; CHECK: inner_loop_ph.split:852; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]853; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]854; CHECK: inner_loop_begin:855; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])856; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4857; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]858; CHECK: inner_loop_exit:859; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1860; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]861; CHECK: loop_latch:862; CHECK-NEXT: br label [[LOOP_BEGIN]]863; CHECK: loop_exit.loopexit:864; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_BEGIN]] ]865; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]866; CHECK: loop_exit.loopexit1:867; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA_US]], [[INNER_LOOP_EXIT]] ]868; CHECK-NEXT: br label [[LOOP_EXIT]]869; CHECK: loop_exit:870; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]871; CHECK-NEXT: ret i32 [[A_LCSSA]]872;873entry:874 br label %loop_begin875 876loop_begin:877 %b = load i32, ptr %b.ptr878 %v1 = load i1, ptr %ptr879 br i1 %v1, label %loop_latch, label %inner_loop_ph880 881inner_loop_ph:882 %cond = load i1, ptr %cond.ptr883 br label %inner_loop_begin884 885inner_loop_begin:886 call void @sink1(i32 %b)887 %a = load i32, ptr %a.ptr888 br i1 %cond, label %inner_loop_a, label %loop_exit889 890inner_loop_a:891 %v2 = load i1, ptr %ptr892 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin893; The cloned path continues to loop without the exit out of the entire nest.894; The original remains a loop losing the exit edge.895 896inner_loop_exit:897 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]898 %v3 = load i1, ptr %ptr899 br i1 %v3, label %loop_latch, label %loop_exit900 901loop_latch:902 br label %loop_begin903 904loop_exit:905 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]906 ret i32 %a.lcssa907}908 909; Like test11a, but checking that when the whole thing is wrapped in yet910; another loop, we correctly attribute the cloned preheader to that outermost911; loop rather than only handling the case where the preheader is not in any loop912; at all.913define i32 @test12a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {914; CHECK-LABEL: @test12a(915; CHECK-NEXT: entry:916; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]917; CHECK: loop_begin:918; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]919; CHECK: inner_loop_begin:920; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4921; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1922; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]923; CHECK: inner_inner_loop_ph:924; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1925; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]926; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]927; CHECK: inner_inner_loop_ph.split.us:928; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]929; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]930; CHECK: inner_inner_loop_begin.us:931; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])932; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4933; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]934; CHECK: inner_loop_exit.loopexit.split.us:935; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_BEGIN_US]] ]936; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]937; CHECK: inner_inner_loop_ph.split:938; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]939; CHECK: inner_inner_loop_begin:940; CHECK-NEXT: call void @sink1(i32 [[B]])941; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4942; CHECK-NEXT: br label [[INNER_INNER_LOOP_A:%.*]]943; CHECK: inner_inner_loop_a:944; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1945; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_EXIT:%.*]], label [[INNER_INNER_LOOP_BEGIN]]946; CHECK: inner_inner_loop_exit:947; CHECK-NEXT: [[A_INNER_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_A]] ]948; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1949; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]950; CHECK: inner_loop_latch:951; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]952; CHECK: inner_loop_exit.loopexit:953; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]954; CHECK: inner_loop_exit.loopexit1:955; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA]], [[INNER_INNER_LOOP_EXIT]] ]956; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]957; CHECK: inner_loop_exit:958; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]959; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1960; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]961; CHECK: loop_exit:962; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]963; CHECK-NEXT: ret i32 [[A_LCSSA]]964;965entry:966 br label %loop_begin967 968loop_begin:969 br label %inner_loop_begin970 971inner_loop_begin:972 %b = load i32, ptr %b.ptr973 %v1 = load i1, ptr %ptr974 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph975 976inner_inner_loop_ph:977 %cond = load i1, ptr %cond.ptr978 br label %inner_inner_loop_begin979 980inner_inner_loop_begin:981 call void @sink1(i32 %b)982 %a = load i32, ptr %a.ptr983 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_a984 985inner_inner_loop_a:986 %v2 = load i1, ptr %ptr987 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin988; The cloned path doesn't actually loop and is an exit from the outer loop as989; well.990; The original remains a loop losing the exit edge.991 992inner_inner_loop_exit:993 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]994 %v3 = load i1, ptr %ptr995 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit996 997inner_loop_latch:998 br label %inner_loop_begin999 1000inner_loop_exit:1001 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]1002 %v4 = load i1, ptr %ptr1003 br i1 %v4, label %loop_begin, label %loop_exit1004 1005loop_exit:1006 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]1007 ret i32 %a.lcssa1008}1009 1010; Like test11b, but checking that when the whole thing is wrapped in yet1011; another loop, we correctly sink the preheader to the outermost loop rather1012; than only handling the case where the preheader is completely removed from1013; a loop.1014define i32 @test12b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {1015; CHECK-LABEL: @test12b(1016; CHECK-NEXT: entry:1017; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]1018; CHECK: loop_begin:1019; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]1020; CHECK: inner_loop_begin:1021; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 41022; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 11023; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]1024; CHECK: inner_inner_loop_ph:1025; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 11026; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]1027; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]1028; CHECK: inner_inner_loop_ph.split.us:1029; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]1030; CHECK: inner_inner_loop_begin.us:1031; CHECK-NEXT: call void @sink1(i32 [[B]])1032; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 41033; CHECK-NEXT: br label [[INNER_INNER_LOOP_A_US:%.*]]1034; CHECK: inner_inner_loop_a.us:1035; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 11036; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_BEGIN_US]]1037; CHECK: inner_inner_loop_exit.split.us:1038; CHECK-NEXT: [[A_INNER_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_A_US]] ]1039; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT:%.*]]1040; CHECK: inner_inner_loop_ph.split:1041; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]1042; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]1043; CHECK: inner_inner_loop_begin:1044; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])1045; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 41046; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]1047; CHECK: inner_inner_loop_exit:1048; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 11049; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]1050; CHECK: inner_loop_latch:1051; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]1052; CHECK: inner_loop_exit.loopexit:1053; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_BEGIN]] ]1054; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]1055; CHECK: inner_loop_exit.loopexit1:1056; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA_US]], [[INNER_INNER_LOOP_EXIT]] ]1057; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]1058; CHECK: inner_loop_exit:1059; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]1060; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 11061; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]1062; CHECK: loop_exit:1063; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]1064; CHECK-NEXT: ret i32 [[A_LCSSA]]1065;1066entry:1067 br label %loop_begin1068 1069loop_begin:1070 br label %inner_loop_begin1071 1072inner_loop_begin:1073 %b = load i32, ptr %b.ptr1074 %v1 = load i1, ptr %ptr1075 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph1076 1077inner_inner_loop_ph:1078 %cond = load i1, ptr %cond.ptr1079 br label %inner_inner_loop_begin1080 1081inner_inner_loop_begin:1082 call void @sink1(i32 %b)1083 %a = load i32, ptr %a.ptr1084 br i1 %cond, label %inner_inner_loop_a, label %inner_loop_exit1085 1086inner_inner_loop_a:1087 %v2 = load i1, ptr %ptr1088 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin1089; The cloned path continues to loop without the exit out of the entire nest.1090; The original remains a loop losing the exit edge.1091 1092inner_inner_loop_exit:1093 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]1094 %v3 = load i1, ptr %ptr1095 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit1096 1097inner_loop_latch:1098 br label %inner_loop_begin1099 1100inner_loop_exit:1101 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]1102 %v4 = load i1, ptr %ptr1103 br i1 %v4, label %loop_begin, label %loop_exit1104 1105loop_exit:1106 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]1107 ret i32 %a.lcssa1108}1109 1110; Test where the cloned loop has an inner loop that has to be traversed to form1111; the cloned loop, and where this inner loop has multiple blocks, and where the1112; exiting block that connects the inner loop to the cloned loop is not the header1113; block. This ensures that we correctly handle interesting corner cases of1114; traversing back to the header when establishing the cloned loop.1115define i32 @test13a(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {1116; CHECK-LABEL: @test13a(1117; CHECK-NEXT: entry:1118; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]1119; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]1120; CHECK: entry.split.us:1121; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]1122; CHECK: loop_begin.us:1123; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 41124; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 11125; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]1126; CHECK: loop_b.us:1127; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 41128; CHECK-NEXT: br label [[LOOP_B_INNER_PH_US:%.*]]1129; CHECK: loop_b_inner_ph.us:1130; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US:%.*]]1131; CHECK: loop_b_inner_header.us:1132; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 11133; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_B_INNER_LATCH_US:%.*]], label [[LOOP_B_INNER_BODY_US:%.*]]1134; CHECK: loop_b_inner_body.us:1135; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 11136; CHECK-NEXT: br i1 [[V4_US]], label [[LOOP_B_INNER_LATCH_US]], label [[LOOP_B_INNER_EXIT_US:%.*]]1137; CHECK: loop_b_inner_exit.us:1138; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]1139; CHECK: loop_b_inner_latch.us:1140; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US]]1141; CHECK: loop_a.us:1142; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 11143; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[LOOP_LATCH_US]]1144; CHECK: loop_latch.us:1145; CHECK-NEXT: br label [[LOOP_BEGIN_US]]1146; CHECK: loop_exit.split.us:1147; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]1148; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]1149; CHECK: entry.split:1150; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]1151; CHECK: loop_begin:1152; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 41153; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 11154; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]1155; CHECK: loop_a:1156; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 11157; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]], label [[LOOP_LATCH:%.*]]1158; CHECK: loop_b:1159; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 41160; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]1161; CHECK: loop_latch:1162; CHECK-NEXT: br label [[LOOP_BEGIN]]1163; CHECK: loop_exit.split.loopexit:1164; CHECK-NEXT: [[LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]1165; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]1166; CHECK: loop_exit.split:1167; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[B]], [[LOOP_B]] ], [ [[LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]1168; CHECK-NEXT: br label [[LOOP_EXIT]]1169; CHECK: loop_exit:1170; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]1171; CHECK-NEXT: ret i32 [[DOTUS_PHI]]1172;1173entry:1174 br label %loop_begin1175 1176loop_begin:1177 %a = load i32, ptr %a.ptr1178 %v1 = load i1, ptr %ptr1179 br i1 %v1, label %loop_a, label %loop_b1180 1181loop_a:1182 %v2 = load i1, ptr %ptr1183 br i1 %v2, label %loop_exit, label %loop_latch1184 1185loop_b:1186 %b = load i32, ptr %b.ptr1187 br i1 %cond, label %loop_b_inner_ph, label %loop_exit1188 1189loop_b_inner_ph:1190 br label %loop_b_inner_header1191 1192loop_b_inner_header:1193 %v3 = load i1, ptr %ptr1194 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body1195 1196loop_b_inner_body:1197 %v4 = load i1, ptr %ptr1198 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit1199 1200loop_b_inner_latch:1201 br label %loop_b_inner_header1202 1203loop_b_inner_exit:1204 br label %loop_latch1205 1206loop_latch:1207 br label %loop_begin1208; The cloned loop contains an inner loop within it.1209; And the original loop no longer contains an inner loop.1210 1211loop_exit:1212 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]1213 ret i32 %lcssa1214}1215 1216; Test where the original loop has an inner loop that has to be traversed to1217; rebuild the loop, and where this inner loop has multiple blocks, and where1218; the exiting block that connects the inner loop to the original loop is not1219; the header block. This ensures that we correctly handle interesting corner1220; cases of traversing back to the header when re-establishing the original loop1221; still exists after unswitching.1222define i32 @test13b(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {1223; CHECK-LABEL: @test13b(1224; CHECK-NEXT: entry:1225; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]1226; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]1227; CHECK: entry.split.us:1228; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]1229; CHECK: loop_begin.us:1230; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 41231; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 11232; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]1233; CHECK: loop_b.us:1234; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 41235; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]1236; CHECK: loop_a.us:1237; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 11238; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_LATCH_US:%.*]]1239; CHECK: loop_latch.us:1240; CHECK-NEXT: br label [[LOOP_BEGIN_US]]1241; CHECK: loop_exit.split.us.loopexit:1242; CHECK-NEXT: [[LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]1243; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]1244; CHECK: loop_exit.split.us:1245; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[B_US]], [[LOOP_B_US]] ], [ [[LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]1246; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]1247; CHECK: entry.split:1248; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]1249; CHECK: loop_begin:1250; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 41251; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 11252; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]1253; CHECK: loop_a:1254; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 11255; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_LATCH:%.*]]1256; CHECK: loop_b:1257; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 41258; CHECK-NEXT: br label [[LOOP_B_INNER_PH:%.*]]1259; CHECK: loop_b_inner_ph:1260; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER:%.*]]1261; CHECK: loop_b_inner_header:1262; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 11263; CHECK-NEXT: br i1 [[V3]], label [[LOOP_B_INNER_LATCH:%.*]], label [[LOOP_B_INNER_BODY:%.*]]1264; CHECK: loop_b_inner_body:1265; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 11266; CHECK-NEXT: br i1 [[V4]], label [[LOOP_B_INNER_LATCH]], label [[LOOP_B_INNER_EXIT:%.*]]1267; CHECK: loop_b_inner_latch:1268; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER]]1269; CHECK: loop_b_inner_exit:1270; CHECK-NEXT: br label [[LOOP_LATCH]]1271; CHECK: loop_latch:1272; CHECK-NEXT: br label [[LOOP_BEGIN]]1273; CHECK: loop_exit.split:1274; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]1275; CHECK-NEXT: br label [[LOOP_EXIT]]1276; CHECK: loop_exit:1277; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]1278; CHECK-NEXT: ret i32 [[DOTUS_PHI]]1279;1280entry:1281 br label %loop_begin1282 1283loop_begin:1284 %a = load i32, ptr %a.ptr1285 %v1 = load i1, ptr %ptr1286 br i1 %v1, label %loop_a, label %loop_b1287 1288loop_a:1289 %v2 = load i1, ptr %ptr1290 br i1 %v2, label %loop_exit, label %loop_latch1291 1292loop_b:1293 %b = load i32, ptr %b.ptr1294 br i1 %cond, label %loop_exit, label %loop_b_inner_ph1295 1296loop_b_inner_ph:1297 br label %loop_b_inner_header1298 1299loop_b_inner_header:1300 %v3 = load i1, ptr %ptr1301 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body1302 1303loop_b_inner_body:1304 %v4 = load i1, ptr %ptr1305 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit1306 1307loop_b_inner_latch:1308 br label %loop_b_inner_header1309 1310loop_b_inner_exit:1311 br label %loop_latch1312 1313loop_latch:1314 br label %loop_begin1315; The cloned loop doesn't contain an inner loop.1316; But the original loop contains an inner loop that must be traversed.;1317 1318loop_exit:1319 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]1320 ret i32 %lcssa1321}1322 1323; A test reduced out of 400.perlbench that when unswitching the `%stop`1324; condition clones a loop nest outside of a containing loop. This excercises a1325; different cloning path from our other test cases and in turn verifying the1326; resulting structure can catch any failures to correctly clone these nested1327; loops.1328declare void @f()1329declare void @g()1330declare i32 @h(i32 %arg)1331 1332; Test that when we are unswitching and need to rebuild the loop block set we1333; correctly skip past inner loops. We want to use the inner loop to efficiently1334; skip whole subregions of the outer loop blocks but just because the header of1335; the outer loop is also the preheader of an inner loop shouldn't confuse this1336; walk.1337define void @test23(i1 %arg, ptr %ptr) {1338; CHECK-LABEL: @test23(1339; CHECK-NEXT: entry:1340; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]]1341; CHECK-NEXT: br i1 [[ARG_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]1342; CHECK: entry.split.us:1343; CHECK-NEXT: br label [[OUTER_HEADER_US:%.*]]1344; CHECK: outer.header.us:1345; CHECK-NEXT: br label [[INNER_HEADER_US:%.*]]1346; CHECK: inner.header.us:1347; CHECK-NEXT: call void @f()1348; CHECK-NEXT: br label [[INNER_LATCH_US:%.*]]1349; CHECK: inner.latch.us:1350; CHECK-NEXT: [[INNER_COND_US:%.*]] = load i1, ptr [[PTR:%.*]], align 11351; CHECK-NEXT: br i1 [[INNER_COND_US]], label [[INNER_HEADER_US]], label [[OUTER_BODY_US:%.*]]1352; CHECK: outer.body.us:1353; CHECK-NEXT: br label [[OUTER_BODY_LEFT_US:%.*]]1354; CHECK: outer.body.left.us:1355; CHECK-NEXT: call void @f()1356; CHECK-NEXT: br label [[OUTER_LATCH_US:%.*]]1357; CHECK: outer.latch.us:1358; CHECK-NEXT: [[OUTER_COND_US:%.*]] = load i1, ptr [[PTR]], align 11359; CHECK-NEXT: br i1 [[OUTER_COND_US]], label [[OUTER_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]1360; CHECK: exit.split.us:1361; CHECK-NEXT: br label [[EXIT:%.*]]1362; CHECK: entry.split:1363; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]1364; CHECK: outer.header:1365; CHECK-NEXT: br label [[INNER_HEADER:%.*]]1366; CHECK: inner.header:1367; CHECK-NEXT: call void @f()1368; CHECK-NEXT: br label [[INNER_LATCH:%.*]]1369; CHECK: inner.latch:1370; CHECK-NEXT: [[INNER_COND:%.*]] = load i1, ptr [[PTR]], align 11371; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_HEADER]], label [[OUTER_BODY:%.*]]1372; CHECK: outer.body:1373; CHECK-NEXT: br label [[OUTER_BODY_RIGHT:%.*]]1374; CHECK: outer.body.right:1375; CHECK-NEXT: call void @g()1376; CHECK-NEXT: br label [[OUTER_LATCH:%.*]]1377; CHECK: outer.latch:1378; CHECK-NEXT: [[OUTER_COND:%.*]] = load i1, ptr [[PTR]], align 11379; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_HEADER]], label [[EXIT_SPLIT:%.*]]1380; CHECK: exit.split:1381; CHECK-NEXT: br label [[EXIT]]1382; CHECK: exit:1383; CHECK-NEXT: ret void1384;1385entry:1386 br label %outer.header1387; Just verify that we unswitched the correct bits. We should call `@f` twice in1388; one unswitch and `@f` and then `@g` in the other.1389 1390outer.header:1391 br label %inner.header1392 1393inner.header:1394 call void @f()1395 br label %inner.latch1396 1397inner.latch:1398 %inner.cond = load i1, ptr %ptr1399 br i1 %inner.cond, label %inner.header, label %outer.body1400 1401outer.body:1402 br i1 %arg, label %outer.body.left, label %outer.body.right1403 1404outer.body.left:1405 call void @f()1406 br label %outer.latch1407 1408outer.body.right:1409 call void @g()1410 br label %outer.latch1411 1412outer.latch:1413 %outer.cond = load i1, ptr %ptr1414 br i1 %outer.cond, label %outer.header, label %exit1415 1416exit:1417 ret void1418}1419 1420; A test case designed to exercise unusual properties of switches: they1421; can introduce multiple edges to successors. These need lots of special case1422; handling as they get collapsed in many cases (domtree, the unswitch itself)1423; but not in all cases (the PHI node operands).1424define i32 @test29(i32 %arg) {1425; CHECK-LABEL: @test29(1426; CHECK-NEXT: entry:1427; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]1428; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [1429; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]1430; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US]]1431; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1:%.*]]1432; CHECK-NEXT: i32 3, label [[ENTRY_SPLIT]]1433; CHECK-NEXT: ]1434; CHECK: entry.split.us:1435; CHECK-NEXT: br label [[HEADER_US:%.*]]1436; CHECK: header.us:1437; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()1438; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 01439; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]1440; CHECK: dispatch.us:1441; CHECK-NEXT: br label [[BODY_A_US]]1442; CHECK: body.a.us:1443; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]1444; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()1445; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]1446; CHECK-NEXT: br label [[BODY_B_US:%.*]]1447; CHECK: body.b.us:1448; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]1449; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()1450; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]1451; CHECK-NEXT: br label [[BODY_C_US:%.*]]1452; CHECK: body.c.us:1453; CHECK-NEXT: [[TMP_C_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[BODY_B_US]] ]1454; CHECK-NEXT: [[TMP_C_US:%.*]] = call i32 @c()1455; CHECK-NEXT: [[TMP_C_SUM_US:%.*]] = add i32 [[TMP_C_PHI_US]], [[TMP_C_US]]1456; CHECK-NEXT: br label [[LATCH_US:%.*]]1457; CHECK: latch.us:1458; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_C_SUM_US]], 421459; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[EXIT_SPLIT_US:%.*]]1460; CHECK: exit.split.us:1461; CHECK-NEXT: [[LCSSA_PHI_US:%.*]] = phi i32 [ [[TMP_C_SUM_US]], [[LATCH_US]] ]1462; CHECK-NEXT: br label [[EXIT:%.*]]1463; CHECK: entry.split.us1:1464; CHECK-NEXT: br label [[HEADER_US2:%.*]]1465; CHECK: header.us2:1466; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()1467; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 01468; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]1469; CHECK: dispatch.us5:1470; CHECK-NEXT: br label [[BODY_B_US10:%.*]]1471; CHECK: body.a.us6:1472; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]1473; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()1474; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]1475; CHECK-NEXT: br label [[BODY_B_US10]]1476; CHECK: body.b.us10:1477; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]1478; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()1479; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]1480; CHECK-NEXT: br label [[BODY_C_US14:%.*]]1481; CHECK: body.c.us14:1482; CHECK-NEXT: [[TMP_C_PHI_US15:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[BODY_B_US10]] ]1483; CHECK-NEXT: [[TMP_C_US16:%.*]] = call i32 @c()1484; CHECK-NEXT: [[TMP_C_SUM_US17:%.*]] = add i32 [[TMP_C_PHI_US15]], [[TMP_C_US16]]1485; CHECK-NEXT: br label [[LATCH_US18:%.*]]1486; CHECK: latch.us18:1487; CHECK-NEXT: [[CMP2_US19:%.*]] = icmp slt i32 [[TMP_C_SUM_US17]], 421488; CHECK-NEXT: br i1 [[CMP2_US19]], label [[HEADER_US2]], label [[EXIT_SPLIT_SPLIT_US:%.*]]1489; CHECK: exit.split.split.us:1490; CHECK-NEXT: [[LCSSA_PHI_US20:%.*]] = phi i32 [ [[TMP_C_SUM_US17]], [[LATCH_US18]] ]1491; CHECK-NEXT: br label [[EXIT_SPLIT:%.*]]1492; CHECK: entry.split:1493; CHECK-NEXT: br label [[HEADER:%.*]]1494; CHECK: header:1495; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()1496; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 01497; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]1498; CHECK: dispatch:1499; CHECK-NEXT: br label [[BODY_C:%.*]]1500; CHECK: body.a:1501; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]1502; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()1503; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]1504; CHECK-NEXT: br label [[BODY_B:%.*]]1505; CHECK: body.b:1506; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]1507; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()1508; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]1509; CHECK-NEXT: br label [[BODY_C]]1510; CHECK: body.c:1511; CHECK-NEXT: [[TMP_C_PHI:%.*]] = phi i32 [ [[TMP]], [[DISPATCH]] ], [ [[TMP_B_SUM]], [[BODY_B]] ]1512; CHECK-NEXT: [[TMP_C:%.*]] = call i32 @c()1513; CHECK-NEXT: [[TMP_C_SUM:%.*]] = add i32 [[TMP_C_PHI]], [[TMP_C]]1514; CHECK-NEXT: br label [[LATCH:%.*]]1515; CHECK: latch:1516; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_C_SUM]], 421517; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[EXIT_SPLIT_SPLIT:%.*]]1518; CHECK: exit.split.split:1519; CHECK-NEXT: [[LCSSA_PHI:%.*]] = phi i32 [ [[TMP_C_SUM]], [[LATCH]] ]1520; CHECK-NEXT: br label [[EXIT_SPLIT]]1521; CHECK: exit.split:1522; CHECK-NEXT: [[DOTUS_PHI21:%.*]] = phi i32 [ [[LCSSA_PHI]], [[EXIT_SPLIT_SPLIT]] ], [ [[LCSSA_PHI_US20]], [[EXIT_SPLIT_SPLIT_US]] ]1523; CHECK-NEXT: br label [[EXIT]]1524; CHECK: exit:1525; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI21]], [[EXIT_SPLIT]] ], [ [[LCSSA_PHI_US]], [[EXIT_SPLIT_US]] ]1526; CHECK-NEXT: ret i32 [[DOTUS_PHI]]1527;1528entry:1529 br label %header1530 1531header:1532 %tmp = call i32 @d()1533 %cmp1 = icmp eq i32 %tmp, 01534 ; We set up a chain through all the successors of the switch that doesn't1535 ; involve the switch so that we can have interesting PHI nodes in them.1536 br i1 %cmp1, label %body.a, label %dispatch1537 1538dispatch:1539 ; Switch with multiple successors. We arrange the last successor to be the1540 ; default to make the test case easier to read. This has a duplicate edge1541 ; both to the default destination (which is completely superfluous but1542 ; technically valid IR) and to a regular successor.1543 switch i32 %arg, label %body.c [1544 i32 0, label %body.a1545 i32 1, label %body.a1546 i32 2, label %body.b1547 i32 3, label %body.c1548 ]1549 1550body.a:1551 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ], [ %tmp, %dispatch ]1552 %tmp.a = call i32 @a()1553 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a1554 br label %body.b1555; Unswitched 'a' loop.1556 1557body.b:1558 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]1559 %tmp.b = call i32 @b()1560 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b1561 br label %body.c1562; Unswitched 'b' loop.1563 1564body.c:1565 %tmp.c.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.b.sum, %body.b ]1566 %tmp.c = call i32 @c()1567 %tmp.c.sum = add i32 %tmp.c.phi, %tmp.c1568 br label %latch1569; Unswitched 'c' loop.1570 1571latch:1572 %cmp2 = icmp slt i32 %tmp.c.sum, 421573 br i1 %cmp2, label %header, label %exit1574 1575exit:1576 %lcssa.phi = phi i32 [ %tmp.c.sum, %latch ]1577 ret i32 %lcssa.phi1578 1579}1580 1581; Similar to @test29 but designed to have one of the duplicate edges be1582; a loop exit edge as those can in some cases be special. Among other things,1583; this includes an LCSSA phi with multiple entries despite being a dedicated1584; exit block.1585define i32 @test30(i32 %arg) {1586; CHECK-LABEL: @test30(1587; CHECK-NEXT: entry:1588; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]1589; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [1590; CHECK-NEXT: i32 -1, label [[ENTRY_SPLIT]]1591; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]1592; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US1:%.*]]1593; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1]]1594; CHECK-NEXT: ]1595; CHECK: entry.split.us:1596; CHECK-NEXT: br label [[HEADER_US:%.*]]1597; CHECK: header.us:1598; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()1599; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 01600; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]1601; CHECK: dispatch.us:1602; CHECK-NEXT: br label [[BODY_A_US]]1603; CHECK: body.a.us:1604; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]1605; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()1606; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]1607; CHECK-NEXT: br label [[BODY_B_US:%.*]]1608; CHECK: body.b.us:1609; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]1610; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()1611; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]1612; CHECK-NEXT: br label [[LATCH_US:%.*]]1613; CHECK: latch.us:1614; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_B_SUM_US]], 421615; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[LOOP_EXIT2_SPLIT_US:%.*]]1616; CHECK: loop.exit2.split.us:1617; CHECK-NEXT: [[L2_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[LATCH_US]] ]1618; CHECK-NEXT: br label [[LOOP_EXIT2:%.*]]1619; CHECK: entry.split.us1:1620; CHECK-NEXT: br label [[HEADER_US2:%.*]]1621; CHECK: header.us2:1622; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()1623; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 01624; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]1625; CHECK: dispatch.us5:1626; CHECK-NEXT: br label [[BODY_B_US10:%.*]]1627; CHECK: body.a.us6:1628; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]1629; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()1630; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]1631; CHECK-NEXT: br label [[BODY_B_US10]]1632; CHECK: body.b.us10:1633; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]1634; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()1635; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]1636; CHECK-NEXT: br label [[LATCH_US14:%.*]]1637; CHECK: latch.us14:1638; CHECK-NEXT: [[CMP2_US15:%.*]] = icmp slt i32 [[TMP_B_SUM_US13]], 421639; CHECK-NEXT: br i1 [[CMP2_US15]], label [[HEADER_US2]], label [[LOOP_EXIT2_SPLIT_SPLIT_US:%.*]]1640; CHECK: loop.exit2.split.split.us:1641; CHECK-NEXT: [[L2_PHI_US16:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[LATCH_US14]] ]1642; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT:%.*]]1643; CHECK: entry.split:1644; CHECK-NEXT: br label [[HEADER:%.*]]1645; CHECK: header:1646; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()1647; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 01648; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]1649; CHECK: dispatch:1650; CHECK-NEXT: [[TMP_LCSSA:%.*]] = phi i32 [ [[TMP]], [[HEADER]] ]1651; CHECK-NEXT: br label [[LOOP_EXIT1:%.*]]1652; CHECK: body.a:1653; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]1654; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()1655; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]1656; CHECK-NEXT: br label [[BODY_B:%.*]]1657; CHECK: body.b:1658; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]1659; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()1660; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]1661; CHECK-NEXT: br label [[LATCH:%.*]]1662; CHECK: latch:1663; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_B_SUM]], 421664; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[LOOP_EXIT2_SPLIT_SPLIT:%.*]]1665; CHECK: loop.exit1:1666; CHECK-NEXT: [[L1_PHI:%.*]] = phi i32 [ [[TMP_LCSSA]], [[DISPATCH]] ]1667; CHECK-NEXT: br label [[EXIT:%.*]]1668; CHECK: loop.exit2.split.split:1669; CHECK-NEXT: [[L2_PHI:%.*]] = phi i32 [ [[TMP_B_SUM]], [[LATCH]] ]1670; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT]]1671; CHECK: loop.exit2.split:1672; CHECK-NEXT: [[DOTUS_PHI17:%.*]] = phi i32 [ [[L2_PHI]], [[LOOP_EXIT2_SPLIT_SPLIT]] ], [ [[L2_PHI_US16]], [[LOOP_EXIT2_SPLIT_SPLIT_US]] ]1673; CHECK-NEXT: br label [[LOOP_EXIT2]]1674; CHECK: loop.exit2:1675; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI17]], [[LOOP_EXIT2_SPLIT]] ], [ [[L2_PHI_US]], [[LOOP_EXIT2_SPLIT_US]] ]1676; CHECK-NEXT: br label [[EXIT]]1677; CHECK: exit:1678; CHECK-NEXT: [[L_PHI:%.*]] = phi i32 [ [[L1_PHI]], [[LOOP_EXIT1]] ], [ [[DOTUS_PHI]], [[LOOP_EXIT2]] ]1679; CHECK-NEXT: ret i32 [[L_PHI]]1680;1681entry:1682 br label %header1683 1684header:1685 %tmp = call i32 @d()1686 %cmp1 = icmp eq i32 %tmp, 01687 br i1 %cmp1, label %body.a, label %dispatch1688 1689dispatch:1690 switch i32 %arg, label %loop.exit1 [1691 i32 -1, label %loop.exit11692 i32 0, label %body.a1693 i32 1, label %body.b1694 i32 2, label %body.b1695 ]1696 1697body.a:1698 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ]1699 %tmp.a = call i32 @a()1700 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a1701 br label %body.b1702; Unswitched 'a' loop.1703 1704body.b:1705 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]1706 %tmp.b = call i32 @b()1707 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b1708 br label %latch1709; Unswitched 'b' loop.1710 1711latch:1712 %cmp2 = icmp slt i32 %tmp.b.sum, 421713 br i1 %cmp2, label %header, label %loop.exit21714 1715loop.exit1:1716 %l1.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ]1717 br label %exit1718; Unswitched 'exit' loop.1719 1720loop.exit2:1721 %l2.phi = phi i32 [ %tmp.b.sum, %latch ]1722 br label %exit1723 1724exit:1725 %l.phi = phi i32 [ %l1.phi, %loop.exit1 ], [ %l2.phi, %loop.exit2 ]1726 ret i32 %l.phi1727}1728 1729; Unswitch will not actually change the loop nest from:1730; A < B < C1731define void @hoist_inner_loop0() {1732; CHECK-LABEL: @hoist_inner_loop0(1733; CHECK-NEXT: entry:1734; CHECK-NEXT: br label [[A_HEADER:%.*]]1735; CHECK: a.header:1736; CHECK-NEXT: br label [[B_HEADER:%.*]]1737; CHECK: b.header:1738; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()1739; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]1740; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]1741; CHECK: b.header.split.us:1742; CHECK-NEXT: br label [[C_HEADER_US:%.*]]1743; CHECK: c.header.us:1744; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()1745; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]1746; CHECK: b.latch.split.us:1747; CHECK-NEXT: br label [[B_LATCH:%.*]]1748; CHECK: b.header.split:1749; CHECK-NEXT: br label [[C_HEADER:%.*]]1750; CHECK: c.header:1751; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()1752; CHECK-NEXT: br label [[C_LATCH:%.*]]1753; CHECK: c.latch:1754; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()1755; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[B_LATCH_SPLIT:%.*]]1756; CHECK: b.latch.split:1757; CHECK-NEXT: br label [[B_LATCH]]1758; CHECK: b.latch:1759; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()1760; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]1761; CHECK: a.latch:1762; CHECK-NEXT: br label [[A_HEADER]]1763; CHECK: exit:1764; CHECK-NEXT: ret void1765;1766entry:1767 br label %a.header1768 1769a.header:1770 br label %b.header1771 1772b.header:1773 %v1 = call i1 @cond()1774 br label %c.header1775 1776c.header:1777 call i32 @c()1778 br i1 %v1, label %b.latch, label %c.latch1779 1780c.latch:1781 %v2 = call i1 @cond()1782 br i1 %v2, label %c.header, label %b.latch1783 1784b.latch:1785 %v3 = call i1 @cond()1786 br i1 %v3, label %b.header, label %a.latch1787 1788a.latch:1789 br label %a.header1790 1791exit:1792 ret void1793}1794 1795; Unswitch will transform the loop nest from:1796; A < B < C1797; into1798; A < (B, C)1799define void @hoist_inner_loop1(ptr %ptr) {1800; CHECK-LABEL: @hoist_inner_loop1(1801; CHECK-NEXT: entry:1802; CHECK-NEXT: br label [[A_HEADER:%.*]]1803; CHECK: a.header:1804; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 41805; CHECK-NEXT: br label [[B_HEADER:%.*]]1806; CHECK: b.header:1807; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 41808; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()1809; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]1810; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]1811; CHECK: b.header.split.us:1812; CHECK-NEXT: br label [[C_HEADER_US:%.*]]1813; CHECK: c.header.us:1814; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()1815; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]1816; CHECK: b.latch.split.us:1817; CHECK-NEXT: br label [[B_LATCH:%.*]]1818; CHECK: b.header.split:1819; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]1820; CHECK-NEXT: br label [[C_HEADER:%.*]]1821; CHECK: c.header:1822; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()1823; CHECK-NEXT: br label [[C_LATCH:%.*]]1824; CHECK: c.latch:1825; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 41826; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 41827; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()1828; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[A_EXIT_C:%.*]]1829; CHECK: b.latch:1830; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()1831; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_EXIT_B:%.*]]1832; CHECK: a.exit.c:1833; CHECK-NEXT: br label [[A_LATCH:%.*]]1834; CHECK: a.exit.b:1835; CHECK-NEXT: br label [[A_LATCH]]1836; CHECK: a.latch:1837; CHECK-NEXT: br label [[A_HEADER]]1838; CHECK: exit:1839; CHECK-NEXT: ret void1840;1841entry:1842 br label %a.header1843 1844a.header:1845 %x.a = load i32, ptr %ptr1846 br label %b.header1847 1848b.header:1849 %x.b = load i32, ptr %ptr1850 %v1 = call i1 @cond()1851 br label %c.header1852 1853c.header:1854 call i32 @c()1855 br i1 %v1, label %b.latch, label %c.latch1856 1857c.latch:1858 ; Use values from other loops to check LCSSA form.1859 store i32 %x.a, ptr %ptr1860 store i32 %x.b, ptr %ptr1861 %v2 = call i1 @cond()1862 br i1 %v2, label %c.header, label %a.exit.c1863 1864b.latch:1865 %v3 = call i1 @cond()1866 br i1 %v3, label %b.header, label %a.exit.b1867 1868a.exit.c:1869 br label %a.latch1870 1871a.exit.b:1872 br label %a.latch1873 1874a.latch:1875 br label %a.header1876 1877exit:1878 ret void1879}1880 1881; Unswitch will transform the loop nest from:1882; A < B < C1883; into1884; (A < B), C1885define void @hoist_inner_loop2(ptr %ptr) {1886; CHECK-LABEL: @hoist_inner_loop2(1887; CHECK-NEXT: entry:1888; CHECK-NEXT: br label [[A_HEADER:%.*]]1889; CHECK: a.header:1890; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 41891; CHECK-NEXT: br label [[B_HEADER:%.*]]1892; CHECK: b.header:1893; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 41894; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()1895; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]1896; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]1897; CHECK: b.header.split.us:1898; CHECK-NEXT: br label [[C_HEADER_US:%.*]]1899; CHECK: c.header.us:1900; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()1901; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]1902; CHECK: b.latch.split.us:1903; CHECK-NEXT: br label [[B_LATCH:%.*]]1904; CHECK: b.header.split:1905; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]1906; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]1907; CHECK-NEXT: br label [[C_HEADER:%.*]]1908; CHECK: c.header:1909; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()1910; CHECK-NEXT: br label [[C_LATCH:%.*]]1911; CHECK: c.latch:1912; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 41913; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 41914; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()1915; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]1916; CHECK: b.latch:1917; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()1918; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]1919; CHECK: a.latch:1920; CHECK-NEXT: br label [[A_HEADER]]1921; CHECK: exit:1922; CHECK-NEXT: ret void1923;1924entry:1925 br label %a.header1926 1927a.header:1928 %x.a = load i32, ptr %ptr1929 br label %b.header1930 1931b.header:1932 %x.b = load i32, ptr %ptr1933 %v1 = call i1 @cond()1934 br label %c.header1935 1936c.header:1937 call i32 @c()1938 br i1 %v1, label %b.latch, label %c.latch1939 1940c.latch:1941 ; Use values from other loops to check LCSSA form.1942 store i32 %x.a, ptr %ptr1943 store i32 %x.b, ptr %ptr1944 %v2 = call i1 @cond()1945 br i1 %v2, label %c.header, label %exit1946 1947b.latch:1948 %v3 = call i1 @cond()1949 br i1 %v3, label %b.header, label %a.latch1950 1951a.latch:1952 br label %a.header1953 1954exit:1955 ret void1956}1957 1958; Same as @hoist_inner_loop2 but with a nested loop inside the hoisted loop.1959; Unswitch will transform the loop nest from:1960; A < B < C < D1961; into1962; (A < B), (C < D)1963define void @hoist_inner_loop3(ptr %ptr) {1964; CHECK-LABEL: @hoist_inner_loop3(1965; CHECK-NEXT: entry:1966; CHECK-NEXT: br label [[A_HEADER:%.*]]1967; CHECK: a.header:1968; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 41969; CHECK-NEXT: br label [[B_HEADER:%.*]]1970; CHECK: b.header:1971; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 41972; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()1973; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]1974; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]1975; CHECK: b.header.split.us:1976; CHECK-NEXT: br label [[C_HEADER_US:%.*]]1977; CHECK: c.header.us:1978; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()1979; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]1980; CHECK: b.latch.split.us:1981; CHECK-NEXT: br label [[B_LATCH:%.*]]1982; CHECK: b.header.split:1983; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]1984; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]1985; CHECK-NEXT: br label [[C_HEADER:%.*]]1986; CHECK: c.header:1987; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()1988; CHECK-NEXT: br label [[C_BODY:%.*]]1989; CHECK: c.body:1990; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 41991; CHECK-NEXT: br label [[D_HEADER:%.*]]1992; CHECK: d.header:1993; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 41994; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 41995; CHECK-NEXT: store i32 [[X_C]], ptr [[PTR]], align 41996; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()1997; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[C_LATCH:%.*]]1998; CHECK: c.latch:1999; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()2000; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[EXIT:%.*]]2001; CHECK: b.latch:2002; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()2003; CHECK-NEXT: br i1 [[V4]], label [[B_HEADER]], label [[A_LATCH:%.*]]2004; CHECK: a.latch:2005; CHECK-NEXT: br label [[A_HEADER]]2006; CHECK: exit:2007; CHECK-NEXT: ret void2008;2009entry:2010 br label %a.header2011 2012a.header:2013 %x.a = load i32, ptr %ptr2014 br label %b.header2015 2016b.header:2017 %x.b = load i32, ptr %ptr2018 %v1 = call i1 @cond()2019 br label %c.header2020 2021c.header:2022 call i32 @c()2023 br i1 %v1, label %b.latch, label %c.body2024 2025c.body:2026 %x.c = load i32, ptr %ptr2027 br label %d.header2028 2029d.header:2030 ; Use values from other loops to check LCSSA form.2031 store i32 %x.a, ptr %ptr2032 store i32 %x.b, ptr %ptr2033 store i32 %x.c, ptr %ptr2034 %v2 = call i1 @cond()2035 br i1 %v2, label %d.header, label %c.latch2036 2037c.latch:2038 %v3 = call i1 @cond()2039 br i1 %v3, label %c.header, label %exit2040 2041b.latch:2042 %v4 = call i1 @cond()2043 br i1 %v4, label %b.header, label %a.latch2044 2045a.latch:2046 br label %a.header2047 2048exit:2049 ret void2050}2051 2052; This test is designed to exercise checking multiple remaining exits from the2053; loop being unswitched.2054; Unswitch will transform the loop nest from:2055; A < B < C < D2056; into2057; A < B < (C, D)2058define void @hoist_inner_loop4() {2059; CHECK-LABEL: @hoist_inner_loop4(2060; CHECK-NEXT: entry:2061; CHECK-NEXT: br label [[A_HEADER:%.*]]2062; CHECK: a.header:2063; CHECK-NEXT: br label [[B_HEADER:%.*]]2064; CHECK: b.header:2065; CHECK-NEXT: br label [[C_HEADER:%.*]]2066; CHECK: c.header:2067; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()2068; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]2069; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]2070; CHECK: c.header.split.us:2071; CHECK-NEXT: br label [[D_HEADER_US:%.*]]2072; CHECK: d.header.us:2073; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()2074; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]2075; CHECK: c.latch.split.us:2076; CHECK-NEXT: br label [[C_LATCH:%.*]]2077; CHECK: c.header.split:2078; CHECK-NEXT: br label [[D_HEADER:%.*]]2079; CHECK: d.header:2080; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()2081; CHECK-NEXT: br label [[D_EXITING1:%.*]]2082; CHECK: d.exiting1:2083; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()2084; CHECK-NEXT: br i1 [[V2]], label [[D_EXITING2:%.*]], label [[A_LATCH:%.*]]2085; CHECK: d.exiting2:2086; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()2087; CHECK-NEXT: br i1 [[V3]], label [[D_EXITING3:%.*]], label [[LOOPEXIT_D:%.*]]2088; CHECK: d.exiting3:2089; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()2090; CHECK-NEXT: br i1 [[V4]], label [[D_LATCH:%.*]], label [[B_LATCH:%.*]]2091; CHECK: d.latch:2092; CHECK-NEXT: br label [[D_HEADER]]2093; CHECK: c.latch:2094; CHECK-NEXT: [[V5:%.*]] = call i1 @cond()2095; CHECK-NEXT: br i1 [[V5]], label [[C_HEADER]], label [[LOOPEXIT_C:%.*]]2096; CHECK: b.latch:2097; CHECK-NEXT: br label [[B_HEADER]]2098; CHECK: a.latch:2099; CHECK-NEXT: br label [[A_HEADER]]2100; CHECK: loopexit.d:2101; CHECK-NEXT: br label [[EXIT:%.*]]2102; CHECK: loopexit.c:2103; CHECK-NEXT: br label [[EXIT]]2104; CHECK: exit:2105; CHECK-NEXT: ret void2106;2107entry:2108 br label %a.header2109 2110a.header:2111 br label %b.header2112 2113b.header:2114 br label %c.header2115 2116c.header:2117 %v1 = call i1 @cond()2118 br label %d.header2119 2120d.header:2121 call i32 @d()2122 br i1 %v1, label %c.latch, label %d.exiting12123 2124d.exiting1:2125 %v2 = call i1 @cond()2126 br i1 %v2, label %d.exiting2, label %a.latch2127 2128d.exiting2:2129 %v3 = call i1 @cond()2130 br i1 %v3, label %d.exiting3, label %loopexit.d2131 2132d.exiting3:2133 %v4 = call i1 @cond()2134 br i1 %v4, label %d.latch, label %b.latch2135 2136d.latch:2137 br label %d.header2138 2139c.latch:2140 %v5 = call i1 @cond()2141 br i1 %v5, label %c.header, label %loopexit.c2142 2143b.latch:2144 br label %b.header2145 2146a.latch:2147 br label %a.header2148 2149loopexit.d:2150 br label %exit2151 2152loopexit.c:2153 br label %exit2154 2155exit:2156 ret void2157}2158 2159; Unswitch will transform the loop nest from:2160; A < B < C < D2161; into2162; A < ((B < C), D)2163define void @hoist_inner_loop5(ptr %ptr) {2164; CHECK-LABEL: @hoist_inner_loop5(2165; CHECK-NEXT: entry:2166; CHECK-NEXT: br label [[A_HEADER:%.*]]2167; CHECK: a.header:2168; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 42169; CHECK-NEXT: br label [[B_HEADER:%.*]]2170; CHECK: b.header:2171; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 42172; CHECK-NEXT: br label [[C_HEADER:%.*]]2173; CHECK: c.header:2174; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 42175; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()2176; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]2177; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]2178; CHECK: c.header.split.us:2179; CHECK-NEXT: br label [[D_HEADER_US:%.*]]2180; CHECK: d.header.us:2181; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()2182; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]2183; CHECK: c.latch.split.us:2184; CHECK-NEXT: br label [[C_LATCH:%.*]]2185; CHECK: c.header.split:2186; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[C_HEADER]] ]2187; CHECK-NEXT: [[X_C_LCSSA:%.*]] = phi i32 [ [[X_C]], [[C_HEADER]] ]2188; CHECK-NEXT: br label [[D_HEADER:%.*]]2189; CHECK: d.header:2190; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()2191; CHECK-NEXT: br label [[D_LATCH:%.*]]2192; CHECK: d.latch:2193; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 42194; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 42195; CHECK-NEXT: store i32 [[X_C_LCSSA]], ptr [[PTR]], align 42196; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()2197; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[A_LATCH:%.*]]2198; CHECK: c.latch:2199; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()2200; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[B_LATCH:%.*]]2201; CHECK: b.latch:2202; CHECK-NEXT: br label [[B_HEADER]]2203; CHECK: a.latch:2204; CHECK-NEXT: br label [[A_HEADER]]2205; CHECK: exit:2206; CHECK-NEXT: ret void2207;2208entry:2209 br label %a.header2210 2211a.header:2212 %x.a = load i32, ptr %ptr2213 br label %b.header2214 2215b.header:2216 %x.b = load i32, ptr %ptr2217 br label %c.header2218 2219c.header:2220 %x.c = load i32, ptr %ptr2221 %v1 = call i1 @cond()2222 br label %d.header2223 2224d.header:2225 call i32 @d()2226 br i1 %v1, label %c.latch, label %d.latch2227 2228d.latch:2229 ; Use values from other loops to check LCSSA form.2230 store i32 %x.a, ptr %ptr2231 store i32 %x.b, ptr %ptr2232 store i32 %x.c, ptr %ptr2233 %v2 = call i1 @cond()2234 br i1 %v2, label %d.header, label %a.latch2235 2236c.latch:2237 %v3 = call i1 @cond()2238 br i1 %v3, label %c.header, label %b.latch2239 2240b.latch:2241 br label %b.header2242 2243a.latch:2244 br label %a.header2245 2246exit:2247 ret void2248}2249 2250define void @hoist_inner_loop_switch(ptr %ptr) {2251; CHECK-LABEL: @hoist_inner_loop_switch(2252; CHECK-NEXT: entry:2253; CHECK-NEXT: br label [[A_HEADER:%.*]]2254; CHECK: a.header:2255; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 42256; CHECK-NEXT: br label [[B_HEADER:%.*]]2257; CHECK: b.header:2258; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 42259; CHECK-NEXT: [[V1:%.*]] = call i32 @cond.i32()2260; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]2261; CHECK-NEXT: switch i32 [[V1_FR]], label [[B_HEADER_SPLIT:%.*]] [2262; CHECK-NEXT: i32 1, label [[B_HEADER_SPLIT_US:%.*]]2263; CHECK-NEXT: i32 2, label [[B_HEADER_SPLIT_US]]2264; CHECK-NEXT: i32 3, label [[B_HEADER_SPLIT_US]]2265; CHECK-NEXT: ]2266; CHECK: b.header.split.us:2267; CHECK-NEXT: br label [[C_HEADER_US:%.*]]2268; CHECK: c.header.us:2269; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()2270; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]2271; CHECK: b.latch.split.us:2272; CHECK-NEXT: br label [[B_LATCH:%.*]]2273; CHECK: b.header.split:2274; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]2275; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]2276; CHECK-NEXT: br label [[C_HEADER:%.*]]2277; CHECK: c.header:2278; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()2279; CHECK-NEXT: br label [[C_LATCH:%.*]]2280; CHECK: c.latch:2281; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 42282; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 42283; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()2284; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]2285; CHECK: b.latch:2286; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()2287; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]2288; CHECK: a.latch:2289; CHECK-NEXT: br label [[A_HEADER]]2290; CHECK: exit:2291; CHECK-NEXT: ret void2292;2293entry:2294 br label %a.header2295 2296a.header:2297 %x.a = load i32, ptr %ptr2298 br label %b.header2299 2300b.header:2301 %x.b = load i32, ptr %ptr2302 %v1 = call i32 @cond.i32()2303 br label %c.header2304 2305c.header:2306 call i32 @c()2307 switch i32 %v1, label %c.latch [2308 i32 1, label %b.latch2309 i32 2, label %b.latch2310 i32 3, label %b.latch2311 ]2312 2313c.latch:2314 ; Use values from other loops to check LCSSA form.2315 store i32 %x.a, ptr %ptr2316 store i32 %x.b, ptr %ptr2317 %v2 = call i1 @cond()2318 br i1 %v2, label %c.header, label %exit2319 2320b.latch:2321 %v3 = call i1 @cond()2322 br i1 %v3, label %b.header, label %a.latch2323 2324a.latch:2325 br label %a.header2326 2327exit:2328 ret void2329}2330 2331define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c.1, i1 noundef %c.2) {2332; CHECK-LABEL: @test_partial_unswitch_all_conds_guaranteed_non_poison(2333; CHECK-NEXT: entry:2334; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[C_1:%.*]], [[C_2:%.*]]2335; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]2336; CHECK: entry.split.us:2337; CHECK-NEXT: br label [[LOOP_US:%.*]]2338; CHECK: loop.us:2339; CHECK-NEXT: [[TMP1:%.*]] = call i32 @a()2340; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]2341; CHECK: exit.split.us:2342; CHECK-NEXT: br label [[EXIT:%.*]]2343; CHECK: entry.split:2344; CHECK-NEXT: br label [[LOOP:%.*]]2345; CHECK: loop:2346; CHECK-NEXT: [[TMP2:%.*]] = call i32 @a()2347; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false2348; CHECK-NEXT: br i1 [[SEL]], label [[LOOP]], label [[EXIT_SPLIT:%.*]]2349; CHECK: exit.split:2350; CHECK-NEXT: br label [[EXIT]]2351; CHECK: exit:2352; CHECK-NEXT: ret i32 02353;2354entry:2355 br label %loop2356 2357loop:2358 call i32 @a()2359 %sel = select i1 %c.1, i1 %c.2, i1 false2360 br i1 %sel, label %loop, label %exit2361 2362exit:2363 ret i32 02364}2365