1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -freeze-loop-unswitch-cond -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s 3; RUN: opt -freeze-loop-unswitch-cond -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s 4; RUN: opt -freeze-loop-unswitch-cond -simple-loop-unswitch -enable-nontrivial-unswitch -verify-memoryssa -S < %s | FileCheck %s 5 6declare i32 @a() 7declare i32 @b() 8declare i32 @c() 9declare i32 @d() 10 11declare void @sink1(i32) 12declare void @sink2(i32) 13declare void @sink3(i1) 14declare void @sink4(i1) 15 16declare i1 @cond() 17declare i32 @cond.i32() 18 19declare i32 @__CxxFrameHandler3(...) 20 21define i32 @test1_freeze(i1* %ptr0, i1* %ptr1, i1* %ptr2) { 22; CHECK-LABEL: @test1_freeze( 23; CHECK-NEXT: entry: 24; CHECK-NEXT: [[COND1:%.*]] = load i1, i1* [[PTR1:%.*]], align 1 25; CHECK-NEXT: [[COND2:%.*]] = load i1, i1* [[PTR2:%.*]], align 1 26; CHECK-NEXT: br i1 [[COND1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 27; CHECK: entry.split.us: 28; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] 29; CHECK: loop_begin.us: 30; CHECK-NEXT: br label [[LOOP_A_US:%.*]] 31; CHECK: loop_a.us: 32; CHECK-NEXT: [[TMP0:%.*]] = call i32 @a() 33; CHECK-NEXT: br label [[LATCH_US:%.*]] 34; CHECK: latch.us: 35; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR0:%.*]], align 1 36; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] 37; CHECK: loop_exit.split.us: 38; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 39; CHECK: entry.split: 40; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2]] 41; CHECK-NEXT: br i1 [[COND2_FR]], label [[ENTRY_SPLIT_SPLIT_US:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]] 42; CHECK: entry.split.split.us: 43; CHECK-NEXT: br label [[LOOP_BEGIN_US1:%.*]] 44; CHECK: loop_begin.us1: 45; CHECK-NEXT: br label [[LOOP_B_US:%.*]] 46; CHECK: loop_b.us: 47; CHECK-NEXT: [[TMP1:%.*]] = call i32 @b() 48; CHECK-NEXT: br label [[LOOP_B_A_US:%.*]] 49; CHECK: loop_b_a.us: 50; CHECK-NEXT: call void @sink3(i1 true) 51; CHECK-NEXT: br label [[LATCH_US2:%.*]] 52; CHECK: latch.us2: 53; CHECK-NEXT: [[V_US3:%.*]] = load i1, i1* [[PTR0]], align 1 54; CHECK-NEXT: br i1 [[V_US3]], label [[LOOP_BEGIN_US1]], label [[LOOP_EXIT_SPLIT_SPLIT_US:%.*]] 55; CHECK: loop_exit.split.split.us: 56; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]] 57; CHECK: entry.split.split: 58; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 59; CHECK: loop_begin: 60; CHECK-NEXT: br label [[LOOP_B:%.*]] 61; CHECK: loop_b: 62; CHECK-NEXT: [[TMP2:%.*]] = call i32 @b() 63; CHECK-NEXT: br label [[LOOP_B_B:%.*]] 64; CHECK: loop_b_b: 65; CHECK-NEXT: call void @sink4(i1 false) 66; CHECK-NEXT: br label [[LATCH:%.*]] 67; CHECK: latch: 68; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR0]], align 1 69; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT_SPLIT:%.*]] 70; CHECK: loop_exit.split.split: 71; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]] 72; CHECK: loop_exit.split: 73; CHECK-NEXT: br label [[LOOP_EXIT]] 74; CHECK: loop_exit: 75; CHECK-NEXT: ret i32 0 76; 77entry: 78 %cond1 = load i1, i1* %ptr1 79 %cond2 = load i1, i1* %ptr2 80 br label %loop_begin 81 82loop_begin: 83 br i1 %cond1, label %loop_a, label %loop_b 84 85loop_a: 86 call i32 @a() 87 br label %latch 88; The 'loop_a' unswitched loop. 89 90loop_b: 91 call i32 @b() 92 br i1 %cond2, label %loop_b_a, label %loop_b_b 93; The second unswitched condition. 94 95loop_b_a: 96 call void @sink3(i1 %cond2) 97 br label %latch 98; The 'loop_b_a' unswitched loop. 99; %cond2 is replaced to true 100 101loop_b_b: 102 call void @sink4(i1 %cond2) 103 br label %latch 104; The 'loop_b_b' unswitched loop. 105; %cond2 is replaced to false 106 107latch: 108 %v = load i1, i1* %ptr0 109 br i1 %v, label %loop_begin, label %loop_exit 110 111loop_exit: 112 ret i32 0 113} 114 115; Test that when unswitching a deeply nested loop condition in a way that 116; produces a non-loop clone that can reach multiple exit blocks which are part 117; of different outer loops we correctly divide the cloned loop blocks between 118; the outer loops based on reachability. 119define i32 @test7a(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 120; CHECK-LABEL: @test7a( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 123; CHECK: loop_begin: 124; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 125; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 126; CHECK: inner_loop_begin: 127; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ] 128; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 129; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 130; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 131; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]] 132; CHECK: inner_loop_begin.split.us: 133; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 134; CHECK: inner_inner_loop_begin.us: 135; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 136; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]] 137; CHECK: inner_inner_loop_b.us: 138; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1 139; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US_LOOPEXIT:%.*]] 140; CHECK: inner_inner_loop_a.us: 141; CHECK-NEXT: [[A_PHI_LCSSA10:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN_US]] ] 142; CHECK-NEXT: [[B_LCSSA6:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN_US]] ] 143; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 144; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]] 145; CHECK: inner_inner_loop_c.us.loopexit: 146; CHECK-NEXT: br label [[INNER_INNER_LOOP_C_US]] 147; CHECK: inner_inner_loop_c.us: 148; CHECK-NEXT: [[V4_US:%.*]] = load i1, i1* [[PTR]], align 1 149; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]] 150; CHECK: inner_inner_loop_d.us: 151; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] 152; CHECK: inner_inner_loop_exit.split.us: 153; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 154; CHECK: loop_exit.split.us: 155; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI_LCSSA10]], [[INNER_INNER_LOOP_A_US]] ] 156; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B_LCSSA6]], [[INNER_INNER_LOOP_A_US]] ] 157; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 158; CHECK: inner_loop_exit.loopexit.split.us: 159; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 160; CHECK: inner_loop_begin.split: 161; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 162; CHECK: inner_inner_loop_begin: 163; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 164; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]] 165; CHECK: inner_inner_loop_a: 166; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 167; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]] 168; CHECK: inner_inner_loop_b: 169; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 170; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C]] 171; CHECK: inner_inner_loop_c: 172; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 173; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]] 174; CHECK: inner_inner_loop_d: 175; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]] 176; CHECK: inner_inner_loop_exit.split: 177; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 178; CHECK: inner_inner_loop_exit: 179; CHECK-NEXT: [[A2]] = load i32, i32* [[A_PTR]], align 4 180; CHECK-NEXT: [[V5:%.*]] = load i1, i1* [[PTR]], align 1 181; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]] 182; CHECK: inner_loop_exit.loopexit.split: 183; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]] 184; CHECK: inner_loop_exit.loopexit: 185; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 186; CHECK: inner_loop_exit.loopexit1: 187; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 188; CHECK: inner_loop_exit: 189; CHECK-NEXT: br label [[LOOP_BEGIN]] 190; CHECK: loop_exit.split: 191; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ] 192; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A]] ] 193; CHECK-NEXT: br label [[LOOP_EXIT]] 194; CHECK: loop_exit: 195; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 196; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 197; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]] 198; CHECK-NEXT: ret i32 [[RESULT]] 199; 200entry: 201 br label %loop_begin 202 203loop_begin: 204 %a = load i32, i32* %a.ptr 205 br label %inner_loop_begin 206 207inner_loop_begin: 208 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ] 209 %cond = load i1, i1* %cond.ptr 210 %b = load i32, i32* %b.ptr 211 br label %inner_inner_loop_begin 212 213inner_inner_loop_begin: 214 %v1 = load i1, i1* %ptr 215 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b 216 217inner_inner_loop_a: 218 %v2 = load i1, i1* %ptr 219 br i1 %v2, label %loop_exit, label %inner_inner_loop_c 220 221inner_inner_loop_b: 222 %v3 = load i1, i1* %ptr 223 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c 224 225inner_inner_loop_c: 226 %v4 = load i1, i1* %ptr 227 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d 228 229inner_inner_loop_d: 230 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_begin 231; The cloned copy that always exits with the adjustments required to fix up 232; loop exits. 233; The original copy that continues to loop. 234 235inner_inner_loop_exit: 236 %a2 = load i32, i32* %a.ptr 237 %v5 = load i1, i1* %ptr 238 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin 239 240inner_loop_exit: 241 br label %loop_begin 242 243loop_exit: 244 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ] 245 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ] 246 %result = add i32 %a.lcssa, %b.lcssa 247 ret i32 %result 248} 249 250; Same pattern as @test7a but here the original loop becomes a non-loop that 251; can reach multiple exit blocks which are part of different outer loops. 252define i32 @test7b(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 253; CHECK-LABEL: @test7b( 254; CHECK-NEXT: entry: 255; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 256; CHECK: loop_begin: 257; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 258; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 259; CHECK: inner_loop_begin: 260; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ] 261; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 262; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 263; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 264; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]] 265; CHECK: inner_loop_begin.split.us: 266; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 267; CHECK: inner_inner_loop_begin.us: 268; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 269; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]] 270; CHECK: inner_inner_loop_b.us: 271; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1 272; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]] 273; CHECK: inner_inner_loop_a.us: 274; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 275; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US]] 276; CHECK: inner_inner_loop_c.us: 277; CHECK-NEXT: [[V4_US:%.*]] = load i1, i1* [[PTR]], align 1 278; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]] 279; CHECK: inner_inner_loop_d.us: 280; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]] 281; CHECK: inner_inner_loop_exit.split.us: 282; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 283; CHECK: loop_exit.split.us: 284; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ] 285; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A_US]] ] 286; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 287; CHECK: inner_loop_exit.loopexit.split.us: 288; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 289; CHECK: inner_loop_begin.split: 290; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 291; CHECK: inner_inner_loop_begin: 292; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 293; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]] 294; CHECK: inner_inner_loop_a: 295; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN]] ] 296; CHECK-NEXT: [[B_LCSSA3:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN]] ] 297; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 298; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]] 299; CHECK: inner_inner_loop_b: 300; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 301; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C_LOOPEXIT:%.*]] 302; CHECK: inner_inner_loop_c.loopexit: 303; CHECK-NEXT: br label [[INNER_INNER_LOOP_C]] 304; CHECK: inner_inner_loop_c: 305; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 306; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]] 307; CHECK: inner_inner_loop_d: 308; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] 309; CHECK: inner_inner_loop_exit.split: 310; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 311; CHECK: inner_inner_loop_exit: 312; CHECK-NEXT: [[A2]] = load i32, i32* [[A_PTR]], align 4 313; CHECK-NEXT: [[V5:%.*]] = load i1, i1* [[PTR]], align 1 314; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]] 315; CHECK: inner_loop_exit.loopexit.split: 316; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]] 317; CHECK: inner_loop_exit.loopexit: 318; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 319; CHECK: inner_loop_exit.loopexit1: 320; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 321; CHECK: inner_loop_exit: 322; CHECK-NEXT: br label [[LOOP_BEGIN]] 323; CHECK: loop_exit.split: 324; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_INNER_LOOP_A]] ] 325; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B_LCSSA3]], [[INNER_INNER_LOOP_A]] ] 326; CHECK-NEXT: br label [[LOOP_EXIT]] 327; CHECK: loop_exit: 328; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 329; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 330; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]] 331; CHECK-NEXT: ret i32 [[RESULT]] 332; 333entry: 334 br label %loop_begin 335 336loop_begin: 337 %a = load i32, i32* %a.ptr 338 br label %inner_loop_begin 339 340inner_loop_begin: 341 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ] 342 %cond = load i1, i1* %cond.ptr 343 %b = load i32, i32* %b.ptr 344 br label %inner_inner_loop_begin 345 346inner_inner_loop_begin: 347 %v1 = load i1, i1* %ptr 348 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b 349 350inner_inner_loop_a: 351 %v2 = load i1, i1* %ptr 352 br i1 %v2, label %loop_exit, label %inner_inner_loop_c 353 354inner_inner_loop_b: 355 %v3 = load i1, i1* %ptr 356 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c 357 358inner_inner_loop_c: 359 %v4 = load i1, i1* %ptr 360 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d 361 362inner_inner_loop_d: 363 br i1 %cond, label %inner_inner_loop_begin, label %inner_loop_exit 364; The cloned copy that continues looping. 365; The original copy that now always exits and needs adjustments for exit 366; blocks. 367 368inner_inner_loop_exit: 369 %a2 = load i32, i32* %a.ptr 370 %v5 = load i1, i1* %ptr 371 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin 372 373inner_loop_exit: 374 br label %loop_begin 375 376loop_exit: 377 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ] 378 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ] 379 %result = add i32 %a.lcssa, %b.lcssa 380 ret i32 %result 381} 382 383; Test that when the exit block set of an inner loop changes to start at a less 384; high level of the loop nest we correctly hoist the loop up the nest. 385define i32 @test8a(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 386; CHECK-LABEL: @test8a( 387; CHECK-NEXT: entry: 388; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 389; CHECK: loop_begin: 390; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 391; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 392; CHECK: inner_loop_begin: 393; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ] 394; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 395; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 396; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 397; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]] 398; CHECK: inner_loop_begin.split.us: 399; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ] 400; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 401; CHECK: inner_inner_loop_begin.us: 402; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 403; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]] 404; CHECK: inner_inner_loop_b.us: 405; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH_US:%.*]] 406; CHECK: inner_inner_loop_a.us: 407; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 408; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]] 409; CHECK: inner_inner_loop_latch.us: 410; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]] 411; CHECK: inner_loop_exit.loopexit.split.us: 412; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A_US]] ] 413; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 414; CHECK: inner_loop_begin.split: 415; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 416; CHECK: inner_inner_loop_begin: 417; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 418; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]] 419; CHECK: inner_inner_loop_a: 420; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 421; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]] 422; CHECK: inner_inner_loop_b: 423; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 424; CHECK: inner_inner_loop_latch: 425; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]] 426; CHECK: inner_inner_loop_exit: 427; CHECK-NEXT: [[A2]] = load i32, i32* [[A_PTR]], align 4 428; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 429; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]] 430; CHECK: inner_loop_exit.loopexit.split: 431; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ] 432; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]] 433; CHECK: inner_loop_exit.loopexit: 434; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ] 435; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 436; CHECK: inner_loop_exit.loopexit1: 437; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ] 438; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 439; CHECK: inner_loop_exit: 440; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ] 441; CHECK-NEXT: [[V5:%.*]] = load i1, i1* [[PTR]], align 1 442; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]] 443; CHECK: loop_exit: 444; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ] 445; CHECK-NEXT: ret i32 [[A_LCSSA]] 446; 447entry: 448 br label %loop_begin 449 450loop_begin: 451 %a = load i32, i32* %a.ptr 452 br label %inner_loop_begin 453 454inner_loop_begin: 455 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ] 456 %cond = load i1, i1* %cond.ptr 457 %b = load i32, i32* %b.ptr 458 br label %inner_inner_loop_begin 459 460inner_inner_loop_begin: 461 %v1 = load i1, i1* %ptr 462 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b 463 464inner_inner_loop_a: 465 %v2 = load i1, i1* %ptr 466 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit 467 468inner_inner_loop_b: 469 br i1 %cond, label %inner_inner_loop_latch, label %inner_inner_loop_exit 470 471inner_inner_loop_latch: 472 br label %inner_inner_loop_begin 473; The cloned region is now an exit from the inner loop. 474; The original region exits the loop earlier. 475 476inner_inner_loop_exit: 477 %a2 = load i32, i32* %a.ptr 478 %v4 = load i1, i1* %ptr 479 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin 480 481inner_loop_exit: 482 %v5 = load i1, i1* %ptr 483 br i1 %v5, label %loop_exit, label %loop_begin 484 485loop_exit: 486 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ] 487 ret i32 %a.lcssa 488} 489 490; Same pattern as @test8a but where the original loop looses an exit block and 491; needs to be hoisted up the nest. 492define i32 @test8b(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 493; CHECK-LABEL: @test8b( 494; CHECK-NEXT: entry: 495; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 496; CHECK: loop_begin: 497; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 498; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 499; CHECK: inner_loop_begin: 500; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ] 501; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 502; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 503; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 504; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]] 505; CHECK: inner_loop_begin.split.us: 506; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 507; CHECK: inner_inner_loop_begin.us: 508; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 509; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]] 510; CHECK: inner_inner_loop_b.us: 511; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]] 512; CHECK: inner_inner_loop_a.us: 513; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 514; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]] 515; CHECK: inner_inner_loop_latch.us: 516; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]] 517; CHECK: inner_inner_loop_exit.split.us: 518; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]] 519; CHECK: inner_loop_exit.loopexit.split.us: 520; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ] 521; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 522; CHECK: inner_loop_begin.split: 523; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ] 524; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 525; CHECK: inner_inner_loop_begin: 526; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 527; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]] 528; CHECK: inner_inner_loop_a: 529; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 530; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]] 531; CHECK: inner_inner_loop_b: 532; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH]] 533; CHECK: inner_inner_loop_latch: 534; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]] 535; CHECK: inner_inner_loop_exit: 536; CHECK-NEXT: [[A2]] = load i32, i32* [[A_PTR]], align 4 537; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 538; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]] 539; CHECK: inner_loop_exit.loopexit.split: 540; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A]] ] 541; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]] 542; CHECK: inner_loop_exit.loopexit: 543; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ] 544; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 545; CHECK: inner_loop_exit.loopexit1: 546; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ] 547; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 548; CHECK: inner_loop_exit: 549; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ] 550; CHECK-NEXT: [[V5:%.*]] = load i1, i1* [[PTR]], align 1 551; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]] 552; CHECK: loop_exit: 553; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ] 554; CHECK-NEXT: ret i32 [[A_LCSSA]] 555; 556entry: 557 br label %loop_begin 558 559loop_begin: 560 %a = load i32, i32* %a.ptr 561 br label %inner_loop_begin 562 563inner_loop_begin: 564 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ] 565 %cond = load i1, i1* %cond.ptr 566 %b = load i32, i32* %b.ptr 567 br label %inner_inner_loop_begin 568 569inner_inner_loop_begin: 570 %v1 = load i1, i1* %ptr 571 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b 572 573inner_inner_loop_a: 574 %v2 = load i1, i1* %ptr 575 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit 576 577inner_inner_loop_b: 578 br i1 %cond, label %inner_inner_loop_exit, label %inner_inner_loop_latch 579 580inner_inner_loop_latch: 581 br label %inner_inner_loop_begin 582; The cloned region is similar to before but with one earlier exit. 583; The original region is now an exit in the preheader. 584 585inner_inner_loop_exit: 586 %a2 = load i32, i32* %a.ptr 587 %v4 = load i1, i1* %ptr 588 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin 589 590inner_loop_exit: 591 %v5 = load i1, i1* %ptr 592 br i1 %v5, label %loop_exit, label %loop_begin 593 594loop_exit: 595 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ] 596 ret i32 %a.lcssa 597} 598 599; Test that requires re-forming dedicated exits for the cloned loop. 600define i32 @test10a(i1* %ptr, i1 %cond, i32* %a.ptr) { 601; CHECK-LABEL: @test10a( 602; CHECK-NEXT: entry: 603; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]] 604; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 605; CHECK: entry.split.us: 606; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] 607; CHECK: loop_begin.us: 608; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 609; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 610; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]] 611; CHECK: loop_b.us: 612; CHECK-NEXT: [[A_US_LCSSA:%.*]] = phi i32 [ [[A_US]], [[LOOP_BEGIN_US]] ] 613; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]] 614; CHECK: loop_a.us: 615; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 616; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_BEGIN_BACKEDGE_US:%.*]] 617; CHECK: loop_begin.backedge.us: 618; CHECK-NEXT: br label [[LOOP_BEGIN_US]] 619; CHECK: loop_exit.split.us.loopexit: 620; CHECK-NEXT: [[A_LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ] 621; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]] 622; CHECK: loop_exit.split.us: 623; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US_LCSSA]], [[LOOP_B_US]] ], [ [[A_LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ] 624; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 625; CHECK: entry.split: 626; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 627; CHECK: loop_begin: 628; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 629; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 630; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] 631; CHECK: loop_a: 632; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 633; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_BEGIN_BACKEDGE:%.*]] 634; CHECK: loop_begin.backedge: 635; CHECK-NEXT: br label [[LOOP_BEGIN]] 636; CHECK: loop_b: 637; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE]] 638; CHECK: loop_exit.split: 639; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ] 640; CHECK-NEXT: br label [[LOOP_EXIT]] 641; CHECK: loop_exit: 642; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 643; CHECK-NEXT: ret i32 [[DOTUS_PHI]] 644; 645entry: 646 br label %loop_begin 647 648loop_begin: 649 %a = load i32, i32* %a.ptr 650 %v1 = load i1, i1* %ptr 651 br i1 %v1, label %loop_a, label %loop_b 652 653loop_a: 654 %v2 = load i1, i1* %ptr 655 br i1 %v2, label %loop_exit, label %loop_begin 656 657loop_b: 658 br i1 %cond, label %loop_exit, label %loop_begin 659; The cloned loop with one edge as a direct exit. 660 661; The original loop without one 'loop_exit' edge. 662 663loop_exit: 664 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ] 665 ret i32 %a.lcssa 666} 667 668; Test that requires re-forming dedicated exits for the original loop. 669define i32 @test10b(i1* %ptr, i1 %cond, i32* %a.ptr) { 670; CHECK-LABEL: @test10b( 671; CHECK-NEXT: entry: 672; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]] 673; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 674; CHECK: entry.split.us: 675; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] 676; CHECK: loop_begin.us: 677; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 678; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 679; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]] 680; CHECK: loop_b.us: 681; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE_US:%.*]] 682; CHECK: loop_a.us: 683; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 684; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_BEGIN_BACKEDGE_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] 685; CHECK: loop_begin.backedge.us: 686; CHECK-NEXT: br label [[LOOP_BEGIN_US]] 687; CHECK: loop_exit.split.us: 688; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ] 689; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 690; CHECK: entry.split: 691; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 692; CHECK: loop_begin: 693; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 694; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 695; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] 696; CHECK: loop_a: 697; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 698; CHECK-NEXT: br i1 [[V2]], label [[LOOP_BEGIN_BACKEDGE:%.*]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]] 699; CHECK: loop_begin.backedge: 700; CHECK-NEXT: br label [[LOOP_BEGIN]] 701; CHECK: loop_b: 702; CHECK-NEXT: [[A_LCSSA1:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ] 703; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]] 704; CHECK: loop_exit.split.loopexit: 705; CHECK-NEXT: [[A_LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ] 706; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]] 707; CHECK: loop_exit.split: 708; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA1]], [[LOOP_B]] ], [ [[A_LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ] 709; CHECK-NEXT: br label [[LOOP_EXIT]] 710; CHECK: loop_exit: 711; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 712; CHECK-NEXT: ret i32 [[DOTUS_PHI]] 713; 714entry: 715 br label %loop_begin 716 717loop_begin: 718 %a = load i32, i32* %a.ptr 719 %v1 = load i1, i1* %ptr 720 br i1 %v1, label %loop_a, label %loop_b 721 722loop_a: 723 %v2 = load i1, i1* %ptr 724 br i1 %v2, label %loop_begin, label %loop_exit 725 726loop_b: 727 br i1 %cond, label %loop_begin, label %loop_exit 728; The cloned loop without one of the exits. 729 730; The original loop without one 'loop_exit' edge. 731 732loop_exit: 733 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ] 734 ret i32 %a.lcssa 735} 736 737; Check that if a cloned inner loop after unswitching doesn't loop and directly 738; exits even an outer loop, we don't add the cloned preheader to the outer 739; loop and do add the needed LCSSA phi nodes for the new exit block from the 740; outer loop. 741define i32 @test11a(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 742; CHECK-LABEL: @test11a( 743; CHECK-NEXT: entry: 744; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 745; CHECK: loop_begin: 746; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 747; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 748; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]] 749; CHECK: inner_loop_ph: 750; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 751; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 752; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]] 753; CHECK: inner_loop_ph.split.us: 754; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ] 755; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]] 756; CHECK: inner_loop_begin.us: 757; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]]) 758; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 759; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]] 760; CHECK: loop_exit.loopexit.split.us: 761; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_BEGIN_US]] ] 762; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]] 763; CHECK: inner_loop_ph.split: 764; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 765; CHECK: inner_loop_begin: 766; CHECK-NEXT: call void @sink1(i32 [[B]]) 767; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 768; CHECK-NEXT: br label [[INNER_LOOP_A:%.*]] 769; CHECK: inner_loop_a: 770; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 771; CHECK-NEXT: br i1 [[V2]], label [[INNER_LOOP_EXIT:%.*]], label [[INNER_LOOP_BEGIN]] 772; CHECK: inner_loop_exit: 773; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_A]] ] 774; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 775; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]] 776; CHECK: loop_latch: 777; CHECK-NEXT: br label [[LOOP_BEGIN]] 778; CHECK: loop_exit.loopexit: 779; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 780; CHECK: loop_exit.loopexit1: 781; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ] 782; CHECK-NEXT: br label [[LOOP_EXIT]] 783; CHECK: loop_exit: 784; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ] 785; CHECK-NEXT: ret i32 [[A_LCSSA]] 786; 787entry: 788 br label %loop_begin 789 790loop_begin: 791 %b = load i32, i32* %b.ptr 792 %v1 = load i1, i1* %ptr 793 br i1 %v1, label %loop_latch, label %inner_loop_ph 794 795inner_loop_ph: 796 %cond = load i1, i1* %cond.ptr 797 br label %inner_loop_begin 798 799inner_loop_begin: 800 call void @sink1(i32 %b) 801 %a = load i32, i32* %a.ptr 802 br i1 %cond, label %loop_exit, label %inner_loop_a 803 804inner_loop_a: 805 %v2 = load i1, i1* %ptr 806 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin 807; The cloned path doesn't actually loop and is an exit from the outer loop as 808; well. 809; The original remains a loop losing the exit edge. 810 811inner_loop_exit: 812 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ] 813 %v3 = load i1, i1* %ptr 814 br i1 %v3, label %loop_latch, label %loop_exit 815 816loop_latch: 817 br label %loop_begin 818 819loop_exit: 820 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ] 821 ret i32 %a.lcssa 822} 823 824; Check that if the original inner loop after unswitching doesn't loop and 825; directly exits even an outer loop, we remove the original preheader from the 826; outer loop and add needed LCSSA phi nodes for the new exit block from the 827; outer loop. 828define i32 @test11b(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 829; CHECK-LABEL: @test11b( 830; CHECK-NEXT: entry: 831; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 832; CHECK: loop_begin: 833; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 834; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 835; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]] 836; CHECK: inner_loop_ph: 837; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 838; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 839; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]] 840; CHECK: inner_loop_ph.split.us: 841; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]] 842; CHECK: inner_loop_begin.us: 843; CHECK-NEXT: call void @sink1(i32 [[B]]) 844; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 845; CHECK-NEXT: br label [[INNER_LOOP_A_US:%.*]] 846; CHECK: inner_loop_a.us: 847; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 848; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_US]] 849; CHECK: inner_loop_exit.split.us: 850; CHECK-NEXT: [[A_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_A_US]] ] 851; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 852; CHECK: inner_loop_ph.split: 853; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ] 854; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 855; CHECK: inner_loop_begin: 856; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]]) 857; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 858; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]] 859; CHECK: inner_loop_exit: 860; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 861; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]] 862; CHECK: loop_latch: 863; CHECK-NEXT: br label [[LOOP_BEGIN]] 864; CHECK: loop_exit.loopexit: 865; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_BEGIN]] ] 866; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 867; CHECK: loop_exit.loopexit1: 868; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA_US]], [[INNER_LOOP_EXIT]] ] 869; CHECK-NEXT: br label [[LOOP_EXIT]] 870; CHECK: loop_exit: 871; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ] 872; CHECK-NEXT: ret i32 [[A_LCSSA]] 873; 874entry: 875 br label %loop_begin 876 877loop_begin: 878 %b = load i32, i32* %b.ptr 879 %v1 = load i1, i1* %ptr 880 br i1 %v1, label %loop_latch, label %inner_loop_ph 881 882inner_loop_ph: 883 %cond = load i1, i1* %cond.ptr 884 br label %inner_loop_begin 885 886inner_loop_begin: 887 call void @sink1(i32 %b) 888 %a = load i32, i32* %a.ptr 889 br i1 %cond, label %inner_loop_a, label %loop_exit 890 891inner_loop_a: 892 %v2 = load i1, i1* %ptr 893 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin 894; The cloned path continues to loop without the exit out of the entire nest. 895; The original remains a loop losing the exit edge. 896 897inner_loop_exit: 898 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ] 899 %v3 = load i1, i1* %ptr 900 br i1 %v3, label %loop_latch, label %loop_exit 901 902loop_latch: 903 br label %loop_begin 904 905loop_exit: 906 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ] 907 ret i32 %a.lcssa 908} 909 910; Like test11a, but checking that when the whole thing is wrapped in yet 911; another loop, we correctly attribute the cloned preheader to that outermost 912; loop rather than only handling the case where the preheader is not in any loop 913; at all. 914define i32 @test12a(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 915; CHECK-LABEL: @test12a( 916; CHECK-NEXT: entry: 917; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 918; CHECK: loop_begin: 919; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 920; CHECK: inner_loop_begin: 921; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 922; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 923; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]] 924; CHECK: inner_inner_loop_ph: 925; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 926; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 927; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]] 928; CHECK: inner_inner_loop_ph.split.us: 929; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ] 930; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 931; CHECK: inner_inner_loop_begin.us: 932; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]]) 933; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 934; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]] 935; CHECK: inner_loop_exit.loopexit.split.us: 936; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_BEGIN_US]] ] 937; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 938; CHECK: inner_inner_loop_ph.split: 939; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 940; CHECK: inner_inner_loop_begin: 941; CHECK-NEXT: call void @sink1(i32 [[B]]) 942; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 943; CHECK-NEXT: br label [[INNER_INNER_LOOP_A:%.*]] 944; CHECK: inner_inner_loop_a: 945; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 946; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_EXIT:%.*]], label [[INNER_INNER_LOOP_BEGIN]] 947; CHECK: inner_inner_loop_exit: 948; CHECK-NEXT: [[A_INNER_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_A]] ] 949; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 950; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]] 951; CHECK: inner_loop_latch: 952; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]] 953; CHECK: inner_loop_exit.loopexit: 954; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 955; CHECK: inner_loop_exit.loopexit1: 956; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA]], [[INNER_INNER_LOOP_EXIT]] ] 957; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 958; CHECK: inner_loop_exit: 959; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ] 960; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 961; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] 962; CHECK: loop_exit: 963; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ] 964; CHECK-NEXT: ret i32 [[A_LCSSA]] 965; 966entry: 967 br label %loop_begin 968 969loop_begin: 970 br label %inner_loop_begin 971 972inner_loop_begin: 973 %b = load i32, i32* %b.ptr 974 %v1 = load i1, i1* %ptr 975 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph 976 977inner_inner_loop_ph: 978 %cond = load i1, i1* %cond.ptr 979 br label %inner_inner_loop_begin 980 981inner_inner_loop_begin: 982 call void @sink1(i32 %b) 983 %a = load i32, i32* %a.ptr 984 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_a 985 986inner_inner_loop_a: 987 %v2 = load i1, i1* %ptr 988 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin 989; The cloned path doesn't actually loop and is an exit from the outer loop as 990; well. 991; The original remains a loop losing the exit edge. 992 993inner_inner_loop_exit: 994 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ] 995 %v3 = load i1, i1* %ptr 996 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit 997 998inner_loop_latch: 999 br label %inner_loop_begin 1000 1001inner_loop_exit: 1002 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ] 1003 %v4 = load i1, i1* %ptr 1004 br i1 %v4, label %loop_begin, label %loop_exit 1005 1006loop_exit: 1007 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ] 1008 ret i32 %a.lcssa 1009} 1010 1011; Like test11b, but checking that when the whole thing is wrapped in yet 1012; another loop, we correctly sink the preheader to the outermost loop rather 1013; than only handling the case where the preheader is completely removed from 1014; a loop. 1015define i32 @test12b(i1* %ptr, i1* %cond.ptr, i32* %a.ptr, i32* %b.ptr) { 1016; CHECK-LABEL: @test12b( 1017; CHECK-NEXT: entry: 1018; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 1019; CHECK: loop_begin: 1020; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]] 1021; CHECK: inner_loop_begin: 1022; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 1023; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 1024; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]] 1025; CHECK: inner_inner_loop_ph: 1026; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[COND_PTR:%.*]], align 1 1027; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] 1028; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]] 1029; CHECK: inner_inner_loop_ph.split.us: 1030; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]] 1031; CHECK: inner_inner_loop_begin.us: 1032; CHECK-NEXT: call void @sink1(i32 [[B]]) 1033; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 1034; CHECK-NEXT: br label [[INNER_INNER_LOOP_A_US:%.*]] 1035; CHECK: inner_inner_loop_a.us: 1036; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 1037; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_BEGIN_US]] 1038; CHECK: inner_inner_loop_exit.split.us: 1039; CHECK-NEXT: [[A_INNER_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_A_US]] ] 1040; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT:%.*]] 1041; CHECK: inner_inner_loop_ph.split: 1042; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ] 1043; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]] 1044; CHECK: inner_inner_loop_begin: 1045; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]]) 1046; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 1047; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]] 1048; CHECK: inner_inner_loop_exit: 1049; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 1050; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]] 1051; CHECK: inner_loop_latch: 1052; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]] 1053; CHECK: inner_loop_exit.loopexit: 1054; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_BEGIN]] ] 1055; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]] 1056; CHECK: inner_loop_exit.loopexit1: 1057; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA_US]], [[INNER_INNER_LOOP_EXIT]] ] 1058; CHECK-NEXT: br label [[INNER_LOOP_EXIT]] 1059; CHECK: inner_loop_exit: 1060; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ] 1061; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 1062; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] 1063; CHECK: loop_exit: 1064; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ] 1065; CHECK-NEXT: ret i32 [[A_LCSSA]] 1066; 1067entry: 1068 br label %loop_begin 1069 1070loop_begin: 1071 br label %inner_loop_begin 1072 1073inner_loop_begin: 1074 %b = load i32, i32* %b.ptr 1075 %v1 = load i1, i1* %ptr 1076 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph 1077 1078inner_inner_loop_ph: 1079 %cond = load i1, i1* %cond.ptr 1080 br label %inner_inner_loop_begin 1081 1082inner_inner_loop_begin: 1083 call void @sink1(i32 %b) 1084 %a = load i32, i32* %a.ptr 1085 br i1 %cond, label %inner_inner_loop_a, label %inner_loop_exit 1086 1087inner_inner_loop_a: 1088 %v2 = load i1, i1* %ptr 1089 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin 1090; The cloned path continues to loop without the exit out of the entire nest. 1091; The original remains a loop losing the exit edge. 1092 1093inner_inner_loop_exit: 1094 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ] 1095 %v3 = load i1, i1* %ptr 1096 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit 1097 1098inner_loop_latch: 1099 br label %inner_loop_begin 1100 1101inner_loop_exit: 1102 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ] 1103 %v4 = load i1, i1* %ptr 1104 br i1 %v4, label %loop_begin, label %loop_exit 1105 1106loop_exit: 1107 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ] 1108 ret i32 %a.lcssa 1109} 1110 1111; Test where the cloned loop has an inner loop that has to be traversed to form 1112; the cloned loop, and where this inner loop has multiple blocks, and where the 1113; exiting block that connects the inner loop to the cloned loop is not the header 1114; block. This ensures that we correctly handle interesting corner cases of 1115; traversing back to the header when establishing the cloned loop. 1116define i32 @test13a(i1* %ptr, i1 %cond, i32* %a.ptr, i32* %b.ptr) { 1117; CHECK-LABEL: @test13a( 1118; CHECK-NEXT: entry: 1119; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]] 1120; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 1121; CHECK: entry.split.us: 1122; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] 1123; CHECK: loop_begin.us: 1124; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 1125; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 1126; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]] 1127; CHECK: loop_b.us: 1128; CHECK-NEXT: [[B_US:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 1129; CHECK-NEXT: br label [[LOOP_B_INNER_PH_US:%.*]] 1130; CHECK: loop_b_inner_ph.us: 1131; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US:%.*]] 1132; CHECK: loop_b_inner_header.us: 1133; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1 1134; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_B_INNER_LATCH_US:%.*]], label [[LOOP_B_INNER_BODY_US:%.*]] 1135; CHECK: loop_b_inner_body.us: 1136; CHECK-NEXT: [[V4_US:%.*]] = load i1, i1* [[PTR]], align 1 1137; CHECK-NEXT: br i1 [[V4_US]], label [[LOOP_B_INNER_LATCH_US]], label [[LOOP_B_INNER_EXIT_US:%.*]] 1138; CHECK: loop_b_inner_exit.us: 1139; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] 1140; CHECK: loop_b_inner_latch.us: 1141; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US]] 1142; CHECK: loop_a.us: 1143; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 1144; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[LOOP_LATCH_US]] 1145; CHECK: loop_latch.us: 1146; CHECK-NEXT: br label [[LOOP_BEGIN_US]] 1147; CHECK: loop_exit.split.us: 1148; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ] 1149; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 1150; CHECK: entry.split: 1151; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 1152; CHECK: loop_begin: 1153; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 1154; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 1155; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] 1156; CHECK: loop_a: 1157; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 1158; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]], label [[LOOP_LATCH:%.*]] 1159; CHECK: loop_b: 1160; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR]], align 4 1161; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]] 1162; CHECK: loop_latch: 1163; CHECK-NEXT: br label [[LOOP_BEGIN]] 1164; CHECK: loop_exit.split.loopexit: 1165; CHECK-NEXT: [[LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ] 1166; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]] 1167; CHECK: loop_exit.split: 1168; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[B]], [[LOOP_B]] ], [ [[LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ] 1169; CHECK-NEXT: br label [[LOOP_EXIT]] 1170; CHECK: loop_exit: 1171; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 1172; CHECK-NEXT: ret i32 [[DOTUS_PHI]] 1173; 1174entry: 1175 br label %loop_begin 1176 1177loop_begin: 1178 %a = load i32, i32* %a.ptr 1179 %v1 = load i1, i1* %ptr 1180 br i1 %v1, label %loop_a, label %loop_b 1181 1182loop_a: 1183 %v2 = load i1, i1* %ptr 1184 br i1 %v2, label %loop_exit, label %loop_latch 1185 1186loop_b: 1187 %b = load i32, i32* %b.ptr 1188 br i1 %cond, label %loop_b_inner_ph, label %loop_exit 1189 1190loop_b_inner_ph: 1191 br label %loop_b_inner_header 1192 1193loop_b_inner_header: 1194 %v3 = load i1, i1* %ptr 1195 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body 1196 1197loop_b_inner_body: 1198 %v4 = load i1, i1* %ptr 1199 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit 1200 1201loop_b_inner_latch: 1202 br label %loop_b_inner_header 1203 1204loop_b_inner_exit: 1205 br label %loop_latch 1206 1207loop_latch: 1208 br label %loop_begin 1209; The cloned loop contains an inner loop within it. 1210; And the original loop no longer contains an inner loop. 1211 1212loop_exit: 1213 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ] 1214 ret i32 %lcssa 1215} 1216 1217; Test where the original loop has an inner loop that has to be traversed to 1218; rebuild the loop, and where this inner loop has multiple blocks, and where 1219; the exiting block that connects the inner loop to the original loop is not 1220; the header block. This ensures that we correctly handle interesting corner 1221; cases of traversing back to the header when re-establishing the original loop 1222; still exists after unswitching. 1223define i32 @test13b(i1* %ptr, i1 %cond, i32* %a.ptr, i32* %b.ptr) { 1224; CHECK-LABEL: @test13b( 1225; CHECK-NEXT: entry: 1226; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]] 1227; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 1228; CHECK: entry.split.us: 1229; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] 1230; CHECK: loop_begin.us: 1231; CHECK-NEXT: [[A_US:%.*]] = load i32, i32* [[A_PTR:%.*]], align 4 1232; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 1233; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]] 1234; CHECK: loop_b.us: 1235; CHECK-NEXT: [[B_US:%.*]] = load i32, i32* [[B_PTR:%.*]], align 4 1236; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]] 1237; CHECK: loop_a.us: 1238; CHECK-NEXT: [[V2_US:%.*]] = load i1, i1* [[PTR]], align 1 1239; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_LATCH_US:%.*]] 1240; CHECK: loop_latch.us: 1241; CHECK-NEXT: br label [[LOOP_BEGIN_US]] 1242; CHECK: loop_exit.split.us.loopexit: 1243; CHECK-NEXT: [[LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ] 1244; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]] 1245; CHECK: loop_exit.split.us: 1246; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[B_US]], [[LOOP_B_US]] ], [ [[LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ] 1247; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] 1248; CHECK: entry.split: 1249; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] 1250; CHECK: loop_begin: 1251; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_PTR]], align 4 1252; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR]], align 1 1253; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] 1254; CHECK: loop_a: 1255; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 1256; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_LATCH:%.*]] 1257; CHECK: loop_b: 1258; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR]], align 4 1259; CHECK-NEXT: br label [[LOOP_B_INNER_PH:%.*]] 1260; CHECK: loop_b_inner_ph: 1261; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER:%.*]] 1262; CHECK: loop_b_inner_header: 1263; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 1264; CHECK-NEXT: br i1 [[V3]], label [[LOOP_B_INNER_LATCH:%.*]], label [[LOOP_B_INNER_BODY:%.*]] 1265; CHECK: loop_b_inner_body: 1266; CHECK-NEXT: [[V4:%.*]] = load i1, i1* [[PTR]], align 1 1267; CHECK-NEXT: br i1 [[V4]], label [[LOOP_B_INNER_LATCH]], label [[LOOP_B_INNER_EXIT:%.*]] 1268; CHECK: loop_b_inner_latch: 1269; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER]] 1270; CHECK: loop_b_inner_exit: 1271; CHECK-NEXT: br label [[LOOP_LATCH]] 1272; CHECK: loop_latch: 1273; CHECK-NEXT: br label [[LOOP_BEGIN]] 1274; CHECK: loop_exit.split: 1275; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ] 1276; CHECK-NEXT: br label [[LOOP_EXIT]] 1277; CHECK: loop_exit: 1278; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ] 1279; CHECK-NEXT: ret i32 [[DOTUS_PHI]] 1280; 1281entry: 1282 br label %loop_begin 1283 1284loop_begin: 1285 %a = load i32, i32* %a.ptr 1286 %v1 = load i1, i1* %ptr 1287 br i1 %v1, label %loop_a, label %loop_b 1288 1289loop_a: 1290 %v2 = load i1, i1* %ptr 1291 br i1 %v2, label %loop_exit, label %loop_latch 1292 1293loop_b: 1294 %b = load i32, i32* %b.ptr 1295 br i1 %cond, label %loop_exit, label %loop_b_inner_ph 1296 1297loop_b_inner_ph: 1298 br label %loop_b_inner_header 1299 1300loop_b_inner_header: 1301 %v3 = load i1, i1* %ptr 1302 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body 1303 1304loop_b_inner_body: 1305 %v4 = load i1, i1* %ptr 1306 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit 1307 1308loop_b_inner_latch: 1309 br label %loop_b_inner_header 1310 1311loop_b_inner_exit: 1312 br label %loop_latch 1313 1314loop_latch: 1315 br label %loop_begin 1316; The cloned loop doesn't contain an inner loop. 1317; But the original loop contains an inner loop that must be traversed.; 1318 1319loop_exit: 1320 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ] 1321 ret i32 %lcssa 1322} 1323 1324; A test reduced out of 400.perlbench that when unswitching the `%stop` 1325; condition clones a loop nest outside of a containing loop. This excercises a 1326; different cloning path from our other test cases and in turn verifying the 1327; resulting structure can catch any failures to correctly clone these nested 1328; loops. 1329declare void @f() 1330declare void @g() 1331declare i32 @h(i32 %arg) 1332 1333; Test that when we are unswitching and need to rebuild the loop block set we 1334; correctly skip past inner loops. We want to use the inner loop to efficiently 1335; skip whole subregions of the outer loop blocks but just because the header of 1336; the outer loop is also the preheader of an inner loop shouldn't confuse this 1337; walk. 1338define void @test23(i1 %arg, i1* %ptr) { 1339; CHECK-LABEL: @test23( 1340; CHECK-NEXT: entry: 1341; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]] 1342; CHECK-NEXT: br i1 [[ARG_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] 1343; CHECK: entry.split.us: 1344; CHECK-NEXT: br label [[OUTER_HEADER_US:%.*]] 1345; CHECK: outer.header.us: 1346; CHECK-NEXT: br label [[INNER_HEADER_US:%.*]] 1347; CHECK: inner.header.us: 1348; CHECK-NEXT: call void @f() 1349; CHECK-NEXT: br label [[INNER_LATCH_US:%.*]] 1350; CHECK: inner.latch.us: 1351; CHECK-NEXT: [[INNER_COND_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 1352; CHECK-NEXT: br i1 [[INNER_COND_US]], label [[INNER_HEADER_US]], label [[OUTER_BODY_US:%.*]] 1353; CHECK: outer.body.us: 1354; CHECK-NEXT: br label [[OUTER_BODY_LEFT_US:%.*]] 1355; CHECK: outer.body.left.us: 1356; CHECK-NEXT: call void @f() 1357; CHECK-NEXT: br label [[OUTER_LATCH_US:%.*]] 1358; CHECK: outer.latch.us: 1359; CHECK-NEXT: [[OUTER_COND_US:%.*]] = load i1, i1* [[PTR]], align 1 1360; CHECK-NEXT: br i1 [[OUTER_COND_US]], label [[OUTER_HEADER_US]], label [[EXIT_SPLIT_US:%.*]] 1361; CHECK: exit.split.us: 1362; CHECK-NEXT: br label [[EXIT:%.*]] 1363; CHECK: entry.split: 1364; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 1365; CHECK: outer.header: 1366; CHECK-NEXT: br label [[INNER_HEADER:%.*]] 1367; CHECK: inner.header: 1368; CHECK-NEXT: call void @f() 1369; CHECK-NEXT: br label [[INNER_LATCH:%.*]] 1370; CHECK: inner.latch: 1371; CHECK-NEXT: [[INNER_COND:%.*]] = load i1, i1* [[PTR]], align 1 1372; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_HEADER]], label [[OUTER_BODY:%.*]] 1373; CHECK: outer.body: 1374; CHECK-NEXT: br label [[OUTER_BODY_RIGHT:%.*]] 1375; CHECK: outer.body.right: 1376; CHECK-NEXT: call void @g() 1377; CHECK-NEXT: br label [[OUTER_LATCH:%.*]] 1378; CHECK: outer.latch: 1379; CHECK-NEXT: [[OUTER_COND:%.*]] = load i1, i1* [[PTR]], align 1 1380; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_HEADER]], label [[EXIT_SPLIT:%.*]] 1381; CHECK: exit.split: 1382; CHECK-NEXT: br label [[EXIT]] 1383; CHECK: exit: 1384; CHECK-NEXT: ret void 1385; 1386entry: 1387 br label %outer.header 1388; Just verify that we unswitched the correct bits. We should call `@f` twice in 1389; one unswitch and `@f` and then `@g` in the other. 1390 1391outer.header: 1392 br label %inner.header 1393 1394inner.header: 1395 call void @f() 1396 br label %inner.latch 1397 1398inner.latch: 1399 %inner.cond = load i1, i1* %ptr 1400 br i1 %inner.cond, label %inner.header, label %outer.body 1401 1402outer.body: 1403 br i1 %arg, label %outer.body.left, label %outer.body.right 1404 1405outer.body.left: 1406 call void @f() 1407 br label %outer.latch 1408 1409outer.body.right: 1410 call void @g() 1411 br label %outer.latch 1412 1413outer.latch: 1414 %outer.cond = load i1, i1* %ptr 1415 br i1 %outer.cond, label %outer.header, label %exit 1416 1417exit: 1418 ret void 1419} 1420 1421; A test case designed to exercise unusual properties of switches: they 1422; can introduce multiple edges to successors. These need lots of special case 1423; handling as they get collapsed in many cases (domtree, the unswitch itself) 1424; but not in all cases (the PHI node operands). 1425define i32 @test29(i32 %arg) { 1426; CHECK-LABEL: @test29( 1427; CHECK-NEXT: entry: 1428; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 1429; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [ 1430; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]] 1431; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US]] 1432; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1:%.*]] 1433; CHECK-NEXT: i32 3, label [[ENTRY_SPLIT]] 1434; CHECK-NEXT: ] 1435; CHECK: entry.split.us: 1436; CHECK-NEXT: br label [[HEADER_US:%.*]] 1437; CHECK: header.us: 1438; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d() 1439; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0 1440; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]] 1441; CHECK: dispatch.us: 1442; CHECK-NEXT: br label [[BODY_A_US]] 1443; CHECK: body.a.us: 1444; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ] 1445; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a() 1446; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]] 1447; CHECK-NEXT: br label [[BODY_B_US:%.*]] 1448; CHECK: body.b.us: 1449; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ] 1450; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b() 1451; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]] 1452; CHECK-NEXT: br label [[BODY_C_US:%.*]] 1453; CHECK: body.c.us: 1454; CHECK-NEXT: [[TMP_C_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[BODY_B_US]] ] 1455; CHECK-NEXT: [[TMP_C_US:%.*]] = call i32 @c() 1456; CHECK-NEXT: [[TMP_C_SUM_US:%.*]] = add i32 [[TMP_C_PHI_US]], [[TMP_C_US]] 1457; CHECK-NEXT: br label [[LATCH_US:%.*]] 1458; CHECK: latch.us: 1459; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_C_SUM_US]], 42 1460; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[EXIT_SPLIT_US:%.*]] 1461; CHECK: exit.split.us: 1462; CHECK-NEXT: [[LCSSA_PHI_US:%.*]] = phi i32 [ [[TMP_C_SUM_US]], [[LATCH_US]] ] 1463; CHECK-NEXT: br label [[EXIT:%.*]] 1464; CHECK: entry.split.us1: 1465; CHECK-NEXT: br label [[HEADER_US2:%.*]] 1466; CHECK: header.us2: 1467; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d() 1468; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0 1469; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]] 1470; CHECK: dispatch.us5: 1471; CHECK-NEXT: br label [[BODY_B_US10:%.*]] 1472; CHECK: body.a.us6: 1473; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ] 1474; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a() 1475; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]] 1476; CHECK-NEXT: br label [[BODY_B_US10]] 1477; CHECK: body.b.us10: 1478; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ] 1479; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b() 1480; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]] 1481; CHECK-NEXT: br label [[BODY_C_US14:%.*]] 1482; CHECK: body.c.us14: 1483; CHECK-NEXT: [[TMP_C_PHI_US15:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[BODY_B_US10]] ] 1484; CHECK-NEXT: [[TMP_C_US16:%.*]] = call i32 @c() 1485; CHECK-NEXT: [[TMP_C_SUM_US17:%.*]] = add i32 [[TMP_C_PHI_US15]], [[TMP_C_US16]] 1486; CHECK-NEXT: br label [[LATCH_US18:%.*]] 1487; CHECK: latch.us18: 1488; CHECK-NEXT: [[CMP2_US19:%.*]] = icmp slt i32 [[TMP_C_SUM_US17]], 42 1489; CHECK-NEXT: br i1 [[CMP2_US19]], label [[HEADER_US2]], label [[EXIT_SPLIT_SPLIT_US:%.*]] 1490; CHECK: exit.split.split.us: 1491; CHECK-NEXT: [[LCSSA_PHI_US20:%.*]] = phi i32 [ [[TMP_C_SUM_US17]], [[LATCH_US18]] ] 1492; CHECK-NEXT: br label [[EXIT_SPLIT:%.*]] 1493; CHECK: entry.split: 1494; CHECK-NEXT: br label [[HEADER:%.*]] 1495; CHECK: header: 1496; CHECK-NEXT: [[TMP:%.*]] = call i32 @d() 1497; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0 1498; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]] 1499; CHECK: dispatch: 1500; CHECK-NEXT: br label [[BODY_C:%.*]] 1501; CHECK: body.a: 1502; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ] 1503; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a() 1504; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]] 1505; CHECK-NEXT: br label [[BODY_B:%.*]] 1506; CHECK: body.b: 1507; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ] 1508; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b() 1509; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]] 1510; CHECK-NEXT: br label [[BODY_C]] 1511; CHECK: body.c: 1512; CHECK-NEXT: [[TMP_C_PHI:%.*]] = phi i32 [ [[TMP]], [[DISPATCH]] ], [ [[TMP_B_SUM]], [[BODY_B]] ] 1513; CHECK-NEXT: [[TMP_C:%.*]] = call i32 @c() 1514; CHECK-NEXT: [[TMP_C_SUM:%.*]] = add i32 [[TMP_C_PHI]], [[TMP_C]] 1515; CHECK-NEXT: br label [[LATCH:%.*]] 1516; CHECK: latch: 1517; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_C_SUM]], 42 1518; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[EXIT_SPLIT_SPLIT:%.*]] 1519; CHECK: exit.split.split: 1520; CHECK-NEXT: [[LCSSA_PHI:%.*]] = phi i32 [ [[TMP_C_SUM]], [[LATCH]] ] 1521; CHECK-NEXT: br label [[EXIT_SPLIT]] 1522; CHECK: exit.split: 1523; CHECK-NEXT: [[DOTUS_PHI21:%.*]] = phi i32 [ [[LCSSA_PHI]], [[EXIT_SPLIT_SPLIT]] ], [ [[LCSSA_PHI_US20]], [[EXIT_SPLIT_SPLIT_US]] ] 1524; CHECK-NEXT: br label [[EXIT]] 1525; CHECK: exit: 1526; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI21]], [[EXIT_SPLIT]] ], [ [[LCSSA_PHI_US]], [[EXIT_SPLIT_US]] ] 1527; CHECK-NEXT: ret i32 [[DOTUS_PHI]] 1528; 1529entry: 1530 br label %header 1531 1532header: 1533 %tmp = call i32 @d() 1534 %cmp1 = icmp eq i32 %tmp, 0 1535 ; We set up a chain through all the successors of the switch that doesn't 1536 ; involve the switch so that we can have interesting PHI nodes in them. 1537 br i1 %cmp1, label %body.a, label %dispatch 1538 1539dispatch: 1540 ; Switch with multiple successors. We arrange the last successor to be the 1541 ; default to make the test case easier to read. This has a duplicate edge 1542 ; both to the default destination (which is completely superfluous but 1543 ; technically valid IR) and to a regular successor. 1544 switch i32 %arg, label %body.c [ 1545 i32 0, label %body.a 1546 i32 1, label %body.a 1547 i32 2, label %body.b 1548 i32 3, label %body.c 1549 ] 1550 1551body.a: 1552 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ], [ %tmp, %dispatch ] 1553 %tmp.a = call i32 @a() 1554 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a 1555 br label %body.b 1556; Unswitched 'a' loop. 1557 1558body.b: 1559 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ] 1560 %tmp.b = call i32 @b() 1561 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b 1562 br label %body.c 1563; Unswitched 'b' loop. 1564 1565body.c: 1566 %tmp.c.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.b.sum, %body.b ] 1567 %tmp.c = call i32 @c() 1568 %tmp.c.sum = add i32 %tmp.c.phi, %tmp.c 1569 br label %latch 1570; Unswitched 'c' loop. 1571 1572latch: 1573 %cmp2 = icmp slt i32 %tmp.c.sum, 42 1574 br i1 %cmp2, label %header, label %exit 1575 1576exit: 1577 %lcssa.phi = phi i32 [ %tmp.c.sum, %latch ] 1578 ret i32 %lcssa.phi 1579 1580} 1581 1582; Similar to @test29 but designed to have one of the duplicate edges be 1583; a loop exit edge as those can in some cases be special. Among other things, 1584; this includes an LCSSA phi with multiple entries despite being a dedicated 1585; exit block. 1586define i32 @test30(i32 %arg) { 1587; CHECK-LABEL: @test30( 1588; CHECK-NEXT: entry: 1589; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 1590; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [ 1591; CHECK-NEXT: i32 -1, label [[ENTRY_SPLIT]] 1592; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]] 1593; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US1:%.*]] 1594; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1]] 1595; CHECK-NEXT: ] 1596; CHECK: entry.split.us: 1597; CHECK-NEXT: br label [[HEADER_US:%.*]] 1598; CHECK: header.us: 1599; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d() 1600; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0 1601; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]] 1602; CHECK: dispatch.us: 1603; CHECK-NEXT: br label [[BODY_A_US]] 1604; CHECK: body.a.us: 1605; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ] 1606; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a() 1607; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]] 1608; CHECK-NEXT: br label [[BODY_B_US:%.*]] 1609; CHECK: body.b.us: 1610; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ] 1611; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b() 1612; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]] 1613; CHECK-NEXT: br label [[LATCH_US:%.*]] 1614; CHECK: latch.us: 1615; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_B_SUM_US]], 42 1616; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[LOOP_EXIT2_SPLIT_US:%.*]] 1617; CHECK: loop.exit2.split.us: 1618; CHECK-NEXT: [[L2_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[LATCH_US]] ] 1619; CHECK-NEXT: br label [[LOOP_EXIT2:%.*]] 1620; CHECK: entry.split.us1: 1621; CHECK-NEXT: br label [[HEADER_US2:%.*]] 1622; CHECK: header.us2: 1623; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d() 1624; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0 1625; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]] 1626; CHECK: dispatch.us5: 1627; CHECK-NEXT: br label [[BODY_B_US10:%.*]] 1628; CHECK: body.a.us6: 1629; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ] 1630; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a() 1631; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]] 1632; CHECK-NEXT: br label [[BODY_B_US10]] 1633; CHECK: body.b.us10: 1634; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ] 1635; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b() 1636; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]] 1637; CHECK-NEXT: br label [[LATCH_US14:%.*]] 1638; CHECK: latch.us14: 1639; CHECK-NEXT: [[CMP2_US15:%.*]] = icmp slt i32 [[TMP_B_SUM_US13]], 42 1640; CHECK-NEXT: br i1 [[CMP2_US15]], label [[HEADER_US2]], label [[LOOP_EXIT2_SPLIT_SPLIT_US:%.*]] 1641; CHECK: loop.exit2.split.split.us: 1642; CHECK-NEXT: [[L2_PHI_US16:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[LATCH_US14]] ] 1643; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT:%.*]] 1644; CHECK: entry.split: 1645; CHECK-NEXT: br label [[HEADER:%.*]] 1646; CHECK: header: 1647; CHECK-NEXT: [[TMP:%.*]] = call i32 @d() 1648; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0 1649; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]] 1650; CHECK: dispatch: 1651; CHECK-NEXT: [[TMP_LCSSA:%.*]] = phi i32 [ [[TMP]], [[HEADER]] ] 1652; CHECK-NEXT: br label [[LOOP_EXIT1:%.*]] 1653; CHECK: body.a: 1654; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ] 1655; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a() 1656; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]] 1657; CHECK-NEXT: br label [[BODY_B:%.*]] 1658; CHECK: body.b: 1659; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ] 1660; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b() 1661; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]] 1662; CHECK-NEXT: br label [[LATCH:%.*]] 1663; CHECK: latch: 1664; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_B_SUM]], 42 1665; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[LOOP_EXIT2_SPLIT_SPLIT:%.*]] 1666; CHECK: loop.exit1: 1667; CHECK-NEXT: [[L1_PHI:%.*]] = phi i32 [ [[TMP_LCSSA]], [[DISPATCH]] ] 1668; CHECK-NEXT: br label [[EXIT:%.*]] 1669; CHECK: loop.exit2.split.split: 1670; CHECK-NEXT: [[L2_PHI:%.*]] = phi i32 [ [[TMP_B_SUM]], [[LATCH]] ] 1671; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT]] 1672; CHECK: loop.exit2.split: 1673; CHECK-NEXT: [[DOTUS_PHI17:%.*]] = phi i32 [ [[L2_PHI]], [[LOOP_EXIT2_SPLIT_SPLIT]] ], [ [[L2_PHI_US16]], [[LOOP_EXIT2_SPLIT_SPLIT_US]] ] 1674; CHECK-NEXT: br label [[LOOP_EXIT2]] 1675; CHECK: loop.exit2: 1676; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI17]], [[LOOP_EXIT2_SPLIT]] ], [ [[L2_PHI_US]], [[LOOP_EXIT2_SPLIT_US]] ] 1677; CHECK-NEXT: br label [[EXIT]] 1678; CHECK: exit: 1679; CHECK-NEXT: [[L_PHI:%.*]] = phi i32 [ [[L1_PHI]], [[LOOP_EXIT1]] ], [ [[DOTUS_PHI]], [[LOOP_EXIT2]] ] 1680; CHECK-NEXT: ret i32 [[L_PHI]] 1681; 1682entry: 1683 br label %header 1684 1685header: 1686 %tmp = call i32 @d() 1687 %cmp1 = icmp eq i32 %tmp, 0 1688 br i1 %cmp1, label %body.a, label %dispatch 1689 1690dispatch: 1691 switch i32 %arg, label %loop.exit1 [ 1692 i32 -1, label %loop.exit1 1693 i32 0, label %body.a 1694 i32 1, label %body.b 1695 i32 2, label %body.b 1696 ] 1697 1698body.a: 1699 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ] 1700 %tmp.a = call i32 @a() 1701 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a 1702 br label %body.b 1703; Unswitched 'a' loop. 1704 1705body.b: 1706 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ] 1707 %tmp.b = call i32 @b() 1708 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b 1709 br label %latch 1710; Unswitched 'b' loop. 1711 1712latch: 1713 %cmp2 = icmp slt i32 %tmp.b.sum, 42 1714 br i1 %cmp2, label %header, label %loop.exit2 1715 1716loop.exit1: 1717 %l1.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ] 1718 br label %exit 1719; Unswitched 'exit' loop. 1720 1721loop.exit2: 1722 %l2.phi = phi i32 [ %tmp.b.sum, %latch ] 1723 br label %exit 1724 1725exit: 1726 %l.phi = phi i32 [ %l1.phi, %loop.exit1 ], [ %l2.phi, %loop.exit2 ] 1727 ret i32 %l.phi 1728} 1729 1730; Unswitch will not actually change the loop nest from: 1731; A < B < C 1732define void @hoist_inner_loop0() { 1733; CHECK-LABEL: @hoist_inner_loop0( 1734; CHECK-NEXT: entry: 1735; CHECK-NEXT: br label [[A_HEADER:%.*]] 1736; CHECK: a.header: 1737; CHECK-NEXT: br label [[B_HEADER:%.*]] 1738; CHECK: b.header: 1739; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 1740; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 1741; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]] 1742; CHECK: b.header.split.us: 1743; CHECK-NEXT: br label [[C_HEADER_US:%.*]] 1744; CHECK: c.header.us: 1745; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c() 1746; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]] 1747; CHECK: b.latch.split.us: 1748; CHECK-NEXT: br label [[B_LATCH:%.*]] 1749; CHECK: b.header.split: 1750; CHECK-NEXT: br label [[C_HEADER:%.*]] 1751; CHECK: c.header: 1752; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c() 1753; CHECK-NEXT: br label [[C_LATCH:%.*]] 1754; CHECK: c.latch: 1755; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 1756; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[B_LATCH_SPLIT:%.*]] 1757; CHECK: b.latch.split: 1758; CHECK-NEXT: br label [[B_LATCH]] 1759; CHECK: b.latch: 1760; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 1761; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]] 1762; CHECK: a.latch: 1763; CHECK-NEXT: br label [[A_HEADER]] 1764; CHECK: exit: 1765; CHECK-NEXT: ret void 1766; 1767entry: 1768 br label %a.header 1769 1770a.header: 1771 br label %b.header 1772 1773b.header: 1774 %v1 = call i1 @cond() 1775 br label %c.header 1776 1777c.header: 1778 call i32 @c() 1779 br i1 %v1, label %b.latch, label %c.latch 1780 1781c.latch: 1782 %v2 = call i1 @cond() 1783 br i1 %v2, label %c.header, label %b.latch 1784 1785b.latch: 1786 %v3 = call i1 @cond() 1787 br i1 %v3, label %b.header, label %a.latch 1788 1789a.latch: 1790 br label %a.header 1791 1792exit: 1793 ret void 1794} 1795 1796; Unswitch will transform the loop nest from: 1797; A < B < C 1798; into 1799; A < (B, C) 1800define void @hoist_inner_loop1(i32* %ptr) { 1801; CHECK-LABEL: @hoist_inner_loop1( 1802; CHECK-NEXT: entry: 1803; CHECK-NEXT: br label [[A_HEADER:%.*]] 1804; CHECK: a.header: 1805; CHECK-NEXT: [[X_A:%.*]] = load i32, i32* [[PTR:%.*]], align 4 1806; CHECK-NEXT: br label [[B_HEADER:%.*]] 1807; CHECK: b.header: 1808; CHECK-NEXT: [[X_B:%.*]] = load i32, i32* [[PTR]], align 4 1809; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 1810; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 1811; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]] 1812; CHECK: b.header.split.us: 1813; CHECK-NEXT: br label [[C_HEADER_US:%.*]] 1814; CHECK: c.header.us: 1815; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c() 1816; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]] 1817; CHECK: b.latch.split.us: 1818; CHECK-NEXT: br label [[B_LATCH:%.*]] 1819; CHECK: b.header.split: 1820; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ] 1821; CHECK-NEXT: br label [[C_HEADER:%.*]] 1822; CHECK: c.header: 1823; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c() 1824; CHECK-NEXT: br label [[C_LATCH:%.*]] 1825; CHECK: c.latch: 1826; CHECK-NEXT: store i32 [[X_A]], i32* [[PTR]], align 4 1827; CHECK-NEXT: store i32 [[X_B_LCSSA]], i32* [[PTR]], align 4 1828; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 1829; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[A_EXIT_C:%.*]] 1830; CHECK: b.latch: 1831; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 1832; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_EXIT_B:%.*]] 1833; CHECK: a.exit.c: 1834; CHECK-NEXT: br label [[A_LATCH:%.*]] 1835; CHECK: a.exit.b: 1836; CHECK-NEXT: br label [[A_LATCH]] 1837; CHECK: a.latch: 1838; CHECK-NEXT: br label [[A_HEADER]] 1839; CHECK: exit: 1840; CHECK-NEXT: ret void 1841; 1842entry: 1843 br label %a.header 1844 1845a.header: 1846 %x.a = load i32, i32* %ptr 1847 br label %b.header 1848 1849b.header: 1850 %x.b = load i32, i32* %ptr 1851 %v1 = call i1 @cond() 1852 br label %c.header 1853 1854c.header: 1855 call i32 @c() 1856 br i1 %v1, label %b.latch, label %c.latch 1857 1858c.latch: 1859 ; Use values from other loops to check LCSSA form. 1860 store i32 %x.a, i32* %ptr 1861 store i32 %x.b, i32* %ptr 1862 %v2 = call i1 @cond() 1863 br i1 %v2, label %c.header, label %a.exit.c 1864 1865b.latch: 1866 %v3 = call i1 @cond() 1867 br i1 %v3, label %b.header, label %a.exit.b 1868 1869a.exit.c: 1870 br label %a.latch 1871 1872a.exit.b: 1873 br label %a.latch 1874 1875a.latch: 1876 br label %a.header 1877 1878exit: 1879 ret void 1880} 1881 1882; Unswitch will transform the loop nest from: 1883; A < B < C 1884; into 1885; (A < B), C 1886define void @hoist_inner_loop2(i32* %ptr) { 1887; CHECK-LABEL: @hoist_inner_loop2( 1888; CHECK-NEXT: entry: 1889; CHECK-NEXT: br label [[A_HEADER:%.*]] 1890; CHECK: a.header: 1891; CHECK-NEXT: [[X_A:%.*]] = load i32, i32* [[PTR:%.*]], align 4 1892; CHECK-NEXT: br label [[B_HEADER:%.*]] 1893; CHECK: b.header: 1894; CHECK-NEXT: [[X_B:%.*]] = load i32, i32* [[PTR]], align 4 1895; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 1896; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 1897; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]] 1898; CHECK: b.header.split.us: 1899; CHECK-NEXT: br label [[C_HEADER_US:%.*]] 1900; CHECK: c.header.us: 1901; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c() 1902; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]] 1903; CHECK: b.latch.split.us: 1904; CHECK-NEXT: br label [[B_LATCH:%.*]] 1905; CHECK: b.header.split: 1906; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ] 1907; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ] 1908; CHECK-NEXT: br label [[C_HEADER:%.*]] 1909; CHECK: c.header: 1910; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c() 1911; CHECK-NEXT: br label [[C_LATCH:%.*]] 1912; CHECK: c.latch: 1913; CHECK-NEXT: store i32 [[X_A_LCSSA]], i32* [[PTR]], align 4 1914; CHECK-NEXT: store i32 [[X_B_LCSSA]], i32* [[PTR]], align 4 1915; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 1916; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]] 1917; CHECK: b.latch: 1918; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 1919; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]] 1920; CHECK: a.latch: 1921; CHECK-NEXT: br label [[A_HEADER]] 1922; CHECK: exit: 1923; CHECK-NEXT: ret void 1924; 1925entry: 1926 br label %a.header 1927 1928a.header: 1929 %x.a = load i32, i32* %ptr 1930 br label %b.header 1931 1932b.header: 1933 %x.b = load i32, i32* %ptr 1934 %v1 = call i1 @cond() 1935 br label %c.header 1936 1937c.header: 1938 call i32 @c() 1939 br i1 %v1, label %b.latch, label %c.latch 1940 1941c.latch: 1942 ; Use values from other loops to check LCSSA form. 1943 store i32 %x.a, i32* %ptr 1944 store i32 %x.b, i32* %ptr 1945 %v2 = call i1 @cond() 1946 br i1 %v2, label %c.header, label %exit 1947 1948b.latch: 1949 %v3 = call i1 @cond() 1950 br i1 %v3, label %b.header, label %a.latch 1951 1952a.latch: 1953 br label %a.header 1954 1955exit: 1956 ret void 1957} 1958 1959; Same as @hoist_inner_loop2 but with a nested loop inside the hoisted loop. 1960; Unswitch will transform the loop nest from: 1961; A < B < C < D 1962; into 1963; (A < B), (C < D) 1964define void @hoist_inner_loop3(i32* %ptr) { 1965; CHECK-LABEL: @hoist_inner_loop3( 1966; CHECK-NEXT: entry: 1967; CHECK-NEXT: br label [[A_HEADER:%.*]] 1968; CHECK: a.header: 1969; CHECK-NEXT: [[X_A:%.*]] = load i32, i32* [[PTR:%.*]], align 4 1970; CHECK-NEXT: br label [[B_HEADER:%.*]] 1971; CHECK: b.header: 1972; CHECK-NEXT: [[X_B:%.*]] = load i32, i32* [[PTR]], align 4 1973; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 1974; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 1975; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]] 1976; CHECK: b.header.split.us: 1977; CHECK-NEXT: br label [[C_HEADER_US:%.*]] 1978; CHECK: c.header.us: 1979; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c() 1980; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]] 1981; CHECK: b.latch.split.us: 1982; CHECK-NEXT: br label [[B_LATCH:%.*]] 1983; CHECK: b.header.split: 1984; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ] 1985; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ] 1986; CHECK-NEXT: br label [[C_HEADER:%.*]] 1987; CHECK: c.header: 1988; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c() 1989; CHECK-NEXT: br label [[C_BODY:%.*]] 1990; CHECK: c.body: 1991; CHECK-NEXT: [[X_C:%.*]] = load i32, i32* [[PTR]], align 4 1992; CHECK-NEXT: br label [[D_HEADER:%.*]] 1993; CHECK: d.header: 1994; CHECK-NEXT: store i32 [[X_A_LCSSA]], i32* [[PTR]], align 4 1995; CHECK-NEXT: store i32 [[X_B_LCSSA]], i32* [[PTR]], align 4 1996; CHECK-NEXT: store i32 [[X_C]], i32* [[PTR]], align 4 1997; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 1998; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[C_LATCH:%.*]] 1999; CHECK: c.latch: 2000; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 2001; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[EXIT:%.*]] 2002; CHECK: b.latch: 2003; CHECK-NEXT: [[V4:%.*]] = call i1 @cond() 2004; CHECK-NEXT: br i1 [[V4]], label [[B_HEADER]], label [[A_LATCH:%.*]] 2005; CHECK: a.latch: 2006; CHECK-NEXT: br label [[A_HEADER]] 2007; CHECK: exit: 2008; CHECK-NEXT: ret void 2009; 2010entry: 2011 br label %a.header 2012 2013a.header: 2014 %x.a = load i32, i32* %ptr 2015 br label %b.header 2016 2017b.header: 2018 %x.b = load i32, i32* %ptr 2019 %v1 = call i1 @cond() 2020 br label %c.header 2021 2022c.header: 2023 call i32 @c() 2024 br i1 %v1, label %b.latch, label %c.body 2025 2026c.body: 2027 %x.c = load i32, i32* %ptr 2028 br label %d.header 2029 2030d.header: 2031 ; Use values from other loops to check LCSSA form. 2032 store i32 %x.a, i32* %ptr 2033 store i32 %x.b, i32* %ptr 2034 store i32 %x.c, i32* %ptr 2035 %v2 = call i1 @cond() 2036 br i1 %v2, label %d.header, label %c.latch 2037 2038c.latch: 2039 %v3 = call i1 @cond() 2040 br i1 %v3, label %c.header, label %exit 2041 2042b.latch: 2043 %v4 = call i1 @cond() 2044 br i1 %v4, label %b.header, label %a.latch 2045 2046a.latch: 2047 br label %a.header 2048 2049exit: 2050 ret void 2051} 2052 2053; This test is designed to exercise checking multiple remaining exits from the 2054; loop being unswitched. 2055; Unswitch will transform the loop nest from: 2056; A < B < C < D 2057; into 2058; A < B < (C, D) 2059define void @hoist_inner_loop4() { 2060; CHECK-LABEL: @hoist_inner_loop4( 2061; CHECK-NEXT: entry: 2062; CHECK-NEXT: br label [[A_HEADER:%.*]] 2063; CHECK: a.header: 2064; CHECK-NEXT: br label [[B_HEADER:%.*]] 2065; CHECK: b.header: 2066; CHECK-NEXT: br label [[C_HEADER:%.*]] 2067; CHECK: c.header: 2068; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 2069; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 2070; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]] 2071; CHECK: c.header.split.us: 2072; CHECK-NEXT: br label [[D_HEADER_US:%.*]] 2073; CHECK: d.header.us: 2074; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d() 2075; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]] 2076; CHECK: c.latch.split.us: 2077; CHECK-NEXT: br label [[C_LATCH:%.*]] 2078; CHECK: c.header.split: 2079; CHECK-NEXT: br label [[D_HEADER:%.*]] 2080; CHECK: d.header: 2081; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d() 2082; CHECK-NEXT: br label [[D_EXITING1:%.*]] 2083; CHECK: d.exiting1: 2084; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 2085; CHECK-NEXT: br i1 [[V2]], label [[D_EXITING2:%.*]], label [[A_LATCH:%.*]] 2086; CHECK: d.exiting2: 2087; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 2088; CHECK-NEXT: br i1 [[V3]], label [[D_EXITING3:%.*]], label [[LOOPEXIT_D:%.*]] 2089; CHECK: d.exiting3: 2090; CHECK-NEXT: [[V4:%.*]] = call i1 @cond() 2091; CHECK-NEXT: br i1 [[V4]], label [[D_LATCH:%.*]], label [[B_LATCH:%.*]] 2092; CHECK: d.latch: 2093; CHECK-NEXT: br label [[D_HEADER]] 2094; CHECK: c.latch: 2095; CHECK-NEXT: [[V5:%.*]] = call i1 @cond() 2096; CHECK-NEXT: br i1 [[V5]], label [[C_HEADER]], label [[LOOPEXIT_C:%.*]] 2097; CHECK: b.latch: 2098; CHECK-NEXT: br label [[B_HEADER]] 2099; CHECK: a.latch: 2100; CHECK-NEXT: br label [[A_HEADER]] 2101; CHECK: loopexit.d: 2102; CHECK-NEXT: br label [[EXIT:%.*]] 2103; CHECK: loopexit.c: 2104; CHECK-NEXT: br label [[EXIT]] 2105; CHECK: exit: 2106; CHECK-NEXT: ret void 2107; 2108entry: 2109 br label %a.header 2110 2111a.header: 2112 br label %b.header 2113 2114b.header: 2115 br label %c.header 2116 2117c.header: 2118 %v1 = call i1 @cond() 2119 br label %d.header 2120 2121d.header: 2122 call i32 @d() 2123 br i1 %v1, label %c.latch, label %d.exiting1 2124 2125d.exiting1: 2126 %v2 = call i1 @cond() 2127 br i1 %v2, label %d.exiting2, label %a.latch 2128 2129d.exiting2: 2130 %v3 = call i1 @cond() 2131 br i1 %v3, label %d.exiting3, label %loopexit.d 2132 2133d.exiting3: 2134 %v4 = call i1 @cond() 2135 br i1 %v4, label %d.latch, label %b.latch 2136 2137d.latch: 2138 br label %d.header 2139 2140c.latch: 2141 %v5 = call i1 @cond() 2142 br i1 %v5, label %c.header, label %loopexit.c 2143 2144b.latch: 2145 br label %b.header 2146 2147a.latch: 2148 br label %a.header 2149 2150loopexit.d: 2151 br label %exit 2152 2153loopexit.c: 2154 br label %exit 2155 2156exit: 2157 ret void 2158} 2159 2160; Unswitch will transform the loop nest from: 2161; A < B < C < D 2162; into 2163; A < ((B < C), D) 2164define void @hoist_inner_loop5(i32* %ptr) { 2165; CHECK-LABEL: @hoist_inner_loop5( 2166; CHECK-NEXT: entry: 2167; CHECK-NEXT: br label [[A_HEADER:%.*]] 2168; CHECK: a.header: 2169; CHECK-NEXT: [[X_A:%.*]] = load i32, i32* [[PTR:%.*]], align 4 2170; CHECK-NEXT: br label [[B_HEADER:%.*]] 2171; CHECK: b.header: 2172; CHECK-NEXT: [[X_B:%.*]] = load i32, i32* [[PTR]], align 4 2173; CHECK-NEXT: br label [[C_HEADER:%.*]] 2174; CHECK: c.header: 2175; CHECK-NEXT: [[X_C:%.*]] = load i32, i32* [[PTR]], align 4 2176; CHECK-NEXT: [[V1:%.*]] = call i1 @cond() 2177; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]] 2178; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]] 2179; CHECK: c.header.split.us: 2180; CHECK-NEXT: br label [[D_HEADER_US:%.*]] 2181; CHECK: d.header.us: 2182; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d() 2183; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]] 2184; CHECK: c.latch.split.us: 2185; CHECK-NEXT: br label [[C_LATCH:%.*]] 2186; CHECK: c.header.split: 2187; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[C_HEADER]] ] 2188; CHECK-NEXT: [[X_C_LCSSA:%.*]] = phi i32 [ [[X_C]], [[C_HEADER]] ] 2189; CHECK-NEXT: br label [[D_HEADER:%.*]] 2190; CHECK: d.header: 2191; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d() 2192; CHECK-NEXT: br label [[D_LATCH:%.*]] 2193; CHECK: d.latch: 2194; CHECK-NEXT: store i32 [[X_A]], i32* [[PTR]], align 4 2195; CHECK-NEXT: store i32 [[X_B_LCSSA]], i32* [[PTR]], align 4 2196; CHECK-NEXT: store i32 [[X_C_LCSSA]], i32* [[PTR]], align 4 2197; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 2198; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[A_LATCH:%.*]] 2199; CHECK: c.latch: 2200; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 2201; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[B_LATCH:%.*]] 2202; CHECK: b.latch: 2203; CHECK-NEXT: br label [[B_HEADER]] 2204; CHECK: a.latch: 2205; CHECK-NEXT: br label [[A_HEADER]] 2206; CHECK: exit: 2207; CHECK-NEXT: ret void 2208; 2209entry: 2210 br label %a.header 2211 2212a.header: 2213 %x.a = load i32, i32* %ptr 2214 br label %b.header 2215 2216b.header: 2217 %x.b = load i32, i32* %ptr 2218 br label %c.header 2219 2220c.header: 2221 %x.c = load i32, i32* %ptr 2222 %v1 = call i1 @cond() 2223 br label %d.header 2224 2225d.header: 2226 call i32 @d() 2227 br i1 %v1, label %c.latch, label %d.latch 2228 2229d.latch: 2230 ; Use values from other loops to check LCSSA form. 2231 store i32 %x.a, i32* %ptr 2232 store i32 %x.b, i32* %ptr 2233 store i32 %x.c, i32* %ptr 2234 %v2 = call i1 @cond() 2235 br i1 %v2, label %d.header, label %a.latch 2236 2237c.latch: 2238 %v3 = call i1 @cond() 2239 br i1 %v3, label %c.header, label %b.latch 2240 2241b.latch: 2242 br label %b.header 2243 2244a.latch: 2245 br label %a.header 2246 2247exit: 2248 ret void 2249} 2250 2251define void @hoist_inner_loop_switch(i32* %ptr) { 2252; CHECK-LABEL: @hoist_inner_loop_switch( 2253; CHECK-NEXT: entry: 2254; CHECK-NEXT: br label [[A_HEADER:%.*]] 2255; CHECK: a.header: 2256; CHECK-NEXT: [[X_A:%.*]] = load i32, i32* [[PTR:%.*]], align 4 2257; CHECK-NEXT: br label [[B_HEADER:%.*]] 2258; CHECK: b.header: 2259; CHECK-NEXT: [[X_B:%.*]] = load i32, i32* [[PTR]], align 4 2260; CHECK-NEXT: [[V1:%.*]] = call i32 @cond.i32() 2261; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 2262; CHECK-NEXT: switch i32 [[V1_FR]], label [[B_HEADER_SPLIT:%.*]] [ 2263; CHECK-NEXT: i32 1, label [[B_HEADER_SPLIT_US:%.*]] 2264; CHECK-NEXT: i32 2, label [[B_HEADER_SPLIT_US]] 2265; CHECK-NEXT: i32 3, label [[B_HEADER_SPLIT_US]] 2266; CHECK-NEXT: ] 2267; CHECK: b.header.split.us: 2268; CHECK-NEXT: br label [[C_HEADER_US:%.*]] 2269; CHECK: c.header.us: 2270; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c() 2271; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]] 2272; CHECK: b.latch.split.us: 2273; CHECK-NEXT: br label [[B_LATCH:%.*]] 2274; CHECK: b.header.split: 2275; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ] 2276; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ] 2277; CHECK-NEXT: br label [[C_HEADER:%.*]] 2278; CHECK: c.header: 2279; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c() 2280; CHECK-NEXT: br label [[C_LATCH:%.*]] 2281; CHECK: c.latch: 2282; CHECK-NEXT: store i32 [[X_A_LCSSA]], i32* [[PTR]], align 4 2283; CHECK-NEXT: store i32 [[X_B_LCSSA]], i32* [[PTR]], align 4 2284; CHECK-NEXT: [[V2:%.*]] = call i1 @cond() 2285; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]] 2286; CHECK: b.latch: 2287; CHECK-NEXT: [[V3:%.*]] = call i1 @cond() 2288; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]] 2289; CHECK: a.latch: 2290; CHECK-NEXT: br label [[A_HEADER]] 2291; CHECK: exit: 2292; CHECK-NEXT: ret void 2293; 2294entry: 2295 br label %a.header 2296 2297a.header: 2298 %x.a = load i32, i32* %ptr 2299 br label %b.header 2300 2301b.header: 2302 %x.b = load i32, i32* %ptr 2303 %v1 = call i32 @cond.i32() 2304 br label %c.header 2305 2306c.header: 2307 call i32 @c() 2308 switch i32 %v1, label %c.latch [ 2309 i32 1, label %b.latch 2310 i32 2, label %b.latch 2311 i32 3, label %b.latch 2312 ] 2313 2314c.latch: 2315 ; Use values from other loops to check LCSSA form. 2316 store i32 %x.a, i32* %ptr 2317 store i32 %x.b, i32* %ptr 2318 %v2 = call i1 @cond() 2319 br i1 %v2, label %c.header, label %exit 2320 2321b.latch: 2322 %v3 = call i1 @cond() 2323 br i1 %v3, label %b.header, label %a.latch 2324 2325a.latch: 2326 br label %a.header 2327 2328exit: 2329 ret void 2330} 2331 2332define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c.1, i1 noundef %c.2) { 2333; CHECK-LABEL: @test_partial_unswitch_all_conds_guaranteed_non_poison( 2334; CHECK-NEXT: entry: 2335; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[C_1:%.*]], [[C_2:%.*]] 2336; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]] 2337; CHECK: entry.split.us: 2338; CHECK-NEXT: br label [[LOOP_US:%.*]] 2339; CHECK: loop.us: 2340; CHECK-NEXT: [[TMP1:%.*]] = call i32 @a() 2341; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]] 2342; CHECK: exit.split.us: 2343; CHECK-NEXT: br label [[EXIT:%.*]] 2344; CHECK: entry.split: 2345; CHECK-NEXT: br label [[LOOP:%.*]] 2346; CHECK: loop: 2347; CHECK-NEXT: [[TMP2:%.*]] = call i32 @a() 2348; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false 2349; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT_SPLIT:%.*]] 2350; CHECK: exit.split: 2351; CHECK-NEXT: br label [[EXIT]] 2352; CHECK: exit: 2353; CHECK-NEXT: ret i32 0 2354; 2355entry: 2356 br label %loop 2357 2358loop: 2359 call i32 @a() 2360 %sel = select i1 %c.1, i1 %c.2, i1 false 2361 br i1 %sel, label %loop, label %exit 2362 2363exit: 2364 ret i32 0 2365} 2366