644 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -p loop-unroll -unroll-full-max-count=0 -S %s | FileCheck %s3 4define i64 @peel_single_block_loop_iv_step_1() {5; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1() {6; CHECK-NEXT: [[ENTRY:.*]]:7; CHECK-NEXT: br label %[[LOOP:.*]]8; CHECK: [[LOOP]]:9; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT1:%.*]], %[[LOOP]] ]10; CHECK-NEXT: call void @foo(i32 20)11; CHECK-NEXT: [[IV_NEXT1]] = add nuw nsw i64 [[IV1]], 112; CHECK-NEXT: [[EC1:%.*]] = icmp ne i64 [[IV_NEXT1]], 6313; CHECK-NEXT: br i1 [[EC1]], label %[[LOOP]], label %[[EXIT_PEEL_BEGIN:.*]], !llvm.loop [[LOOP0:![0-9]+]]14; CHECK: [[EXIT_PEEL_BEGIN]]:15; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT1]], %[[LOOP]] ]16; CHECK-NEXT: br label %[[LOOP_PEEL:.*]]17; CHECK: [[LOOP_PEEL]]:18; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], 6319; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 2020; CHECK-NEXT: call void @foo(i32 [[COND]])21; CHECK-NEXT: [[IV_NEXT:%.*]] = add i64 [[IV]], 122; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 6423; CHECK-NEXT: br i1 [[EC]], label %[[EXIT_PEEL_NEXT:.*]], label %[[EXIT_PEEL_NEXT]]24; CHECK: [[EXIT_PEEL_NEXT]]:25; CHECK-NEXT: br label %[[LOOP_PEEL_NEXT:.*]]26; CHECK: [[LOOP_PEEL_NEXT]]:27; CHECK-NEXT: br label %[[EXIT:.*]]28; CHECK: [[EXIT]]:29; CHECK-NEXT: ret i64 [[IV]]30;31entry:32 br label %loop33 34loop:35 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]36 %cmp = icmp eq i64 %iv, 6337 %cond = select i1 %cmp, i32 10, i32 2038 call void @foo(i32 %cond)39 %iv.next = add i64 %iv, 140 %ec = icmp ne i64 %iv.next, 6441 br i1 %ec, label %loop, label %exit42 43exit:44 ret i64 %iv45}46 47; The predicate %cmp doesn't become known in all iterations after peeling.48define i64 @single_block_loop_iv_step_1_predicate_not_known_true_false_after_peeling() {49; CHECK-LABEL: define i64 @single_block_loop_iv_step_1_predicate_not_known_true_false_after_peeling() {50; CHECK-NEXT: [[ENTRY:.*]]:51; CHECK-NEXT: br label %[[LOOP:.*]]52; CHECK: [[LOOP]]:53; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]54; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[IV]], 255; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[UREM]], 156; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 2057; CHECK-NEXT: call void @foo(i32 [[COND]])58; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 159; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 6460; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]61; CHECK: [[EXIT]]:62; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]63; CHECK-NEXT: ret i64 [[IV_LCSSA]]64;65entry:66 br label %loop67 68loop:69 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]70 %urem = urem i64 %iv, 271 %cmp = icmp eq i64 %urem, 172 %cond = select i1 %cmp, i32 10, i32 2073 call void @foo(i32 %cond)74 %iv.next = add i64 %iv, 175 %ec = icmp ne i64 %iv.next, 6476 br i1 %ec, label %loop, label %exit77 78exit:79 ret i64 %iv80}81 82define i64 @peel_single_block_loop_iv_step_1_eq_pred() {83; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_eq_pred() {84; CHECK-NEXT: [[ENTRY:.*]]:85; CHECK-NEXT: br label %[[LOOP:.*]]86; CHECK: [[LOOP]]:87; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_LCSSA:%.*]], %[[LOOP]] ]88; CHECK-NEXT: call void @foo(i32 20)89; CHECK-NEXT: [[IV_LCSSA]] = add nuw nsw i64 [[IV]], 190; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp eq i64 [[IV_LCSSA]], 6391; CHECK-NEXT: br i1 [[CMP_PEEL]], label %[[EXIT_PEEL_BEGIN:.*]], label %[[LOOP]], !llvm.loop [[LOOP2:![0-9]+]]92; CHECK: [[EXIT_PEEL_BEGIN]]:93; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_LCSSA]], %[[LOOP]] ]94; CHECK-NEXT: br label %[[LOOP_PEEL:.*]]95; CHECK: [[LOOP_PEEL]]:96; CHECK-NEXT: [[CMP_PEEL1:%.*]] = icmp eq i64 [[IV_NEXT_LCSSA]], 6397; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_PEEL1]], i32 10, i32 2098; CHECK-NEXT: call void @foo(i32 [[COND]])99; CHECK-NEXT: [[IV_NEXT:%.*]] = add i64 [[IV_NEXT_LCSSA]], 1100; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 64101; CHECK-NEXT: br i1 [[EC]], label %[[EXIT_PEEL_NEXT:.*]], label %[[EXIT_PEEL_NEXT]]102; CHECK: [[EXIT_PEEL_NEXT]]:103; CHECK-NEXT: br label %[[LOOP_PEEL_NEXT:.*]]104; CHECK: [[LOOP_PEEL_NEXT]]:105; CHECK-NEXT: br label %[[EXIT:.*]]106; CHECK: [[EXIT]]:107; CHECK-NEXT: ret i64 [[IV_NEXT_LCSSA]]108;109entry:110 br label %loop111 112loop:113 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]114 %cmp = icmp eq i64 %iv, 63115 %cond = select i1 %cmp, i32 10, i32 20116 call void @foo(i32 %cond)117 %iv.next = add i64 %iv, 1118 %ec = icmp eq i64 %iv.next, 64119 br i1 %ec, label %exit, label %loop120 121exit:122 ret i64 %iv123}124 125define i64 @peel_single_block_loop_iv_step_1_slt_pred() {126; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_slt_pred() {127; CHECK-NEXT: [[ENTRY:.*]]:128; CHECK-NEXT: br label %[[LOOP:.*]]129; CHECK: [[LOOP]]:130; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]131; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], 63132; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20133; CHECK-NEXT: call void @foo(i32 [[COND]])134; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1135; CHECK-NEXT: [[EC:%.*]] = icmp slt i64 [[IV_NEXT]], 64136; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]137; CHECK: [[EXIT]]:138; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]139; CHECK-NEXT: ret i64 [[IV_LCSSA]]140;141entry:142 br label %loop143 144loop:145 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]146 %cmp = icmp eq i64 %iv, 63147 %cond = select i1 %cmp, i32 10, i32 20148 call void @foo(i32 %cond)149 %iv.next = add i64 %iv, 1150 %ec = icmp slt i64 %iv.next, 64151 br i1 %ec, label %loop, label %exit152 153exit:154 ret i64 %iv155}156 157define i64 @peel_single_block_loop_iv_step_1_nested_loop() {158; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_nested_loop() {159; CHECK-NEXT: [[ENTRY:.*]]:160; CHECK-NEXT: br label %[[OUTER_HEADER:.*]]161; CHECK: [[OUTER_HEADER]]:162; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[OUTER_IV_NEXT:%.*]], %[[OUTER_LATCH:.*]] ]163; CHECK-NEXT: br label %[[LOOP:.*]]164; CHECK: [[LOOP]]:165; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[OUTER_HEADER]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]166; CHECK-NEXT: call void @foo(i32 20)167; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1168; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 63169; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[OUTER_LATCH_PEEL_BEGIN:.*]], !llvm.loop [[LOOP3:![0-9]+]]170; CHECK: [[OUTER_LATCH_PEEL_BEGIN]]:171; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], %[[LOOP]] ]172; CHECK-NEXT: br label %[[LOOP_PEEL:.*]]173; CHECK: [[LOOP_PEEL]]:174; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp eq i64 [[IV_NEXT_LCSSA]], 63175; CHECK-NEXT: [[COND_PEEL:%.*]] = select i1 [[CMP_PEEL]], i32 10, i32 20176; CHECK-NEXT: call void @foo(i32 [[COND_PEEL]])177; CHECK-NEXT: [[IV_NEXT_PEEL:%.*]] = add i64 [[IV_NEXT_LCSSA]], 1178; CHECK-NEXT: [[EC_PEEL:%.*]] = icmp ne i64 [[IV_NEXT_PEEL]], 64179; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[OUTER_LATCH_PEEL_NEXT:.*]], label %[[OUTER_LATCH_PEEL_NEXT]]180; CHECK: [[OUTER_LATCH_PEEL_NEXT]]:181; CHECK-NEXT: br label %[[LOOP_PEEL_NEXT:.*]]182; CHECK: [[LOOP_PEEL_NEXT]]:183; CHECK-NEXT: br label %[[OUTER_LATCH]]184; CHECK: [[OUTER_LATCH]]:185; CHECK-NEXT: call void @foo(i32 1)186; CHECK-NEXT: [[OUTER_IV_NEXT]] = add i64 [[OUTER_IV]], 1187; CHECK-NEXT: [[OUTER_EC:%.*]] = icmp ne i64 [[OUTER_IV_NEXT]], 100188; CHECK-NEXT: br i1 [[OUTER_EC]], label %[[EXIT:.*]], label %[[OUTER_HEADER]]189; CHECK: [[EXIT]]:190; CHECK-NEXT: [[IV_LCSSA_LCSSA:%.*]] = phi i64 [ [[IV_NEXT_LCSSA]], %[[OUTER_LATCH]] ]191; CHECK-NEXT: ret i64 [[IV_LCSSA_LCSSA]]192;193entry:194 br label %outer.header195 196outer.header:197 %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ]198 br label %loop199 200loop:201 %iv = phi i64 [ 0, %outer.header ], [ %iv.next, %loop ]202 %cmp = icmp eq i64 %iv, 63203 %cond = select i1 %cmp, i32 10, i32 20204 call void @foo(i32 %cond)205 %iv.next = add i64 %iv, 1206 %ec = icmp ne i64 %iv.next, 64207 br i1 %ec, label %loop, label %outer.latch208 209outer.latch:210 call void @foo(i32 1)211 %outer.iv.next = add i64 %outer.iv, 1212 %outer.ec = icmp ne i64 %outer.iv.next, 100213 br i1 %outer.ec, label %exit, label %outer.header214 215exit:216 ret i64 %iv217}218 219define i64 @peel_multi_block_loop_iv_step_1() {220; CHECK-LABEL: define i64 @peel_multi_block_loop_iv_step_1() {221; CHECK-NEXT: [[ENTRY:.*]]:222; CHECK-NEXT: br label %[[LOOP:.*]]223; CHECK: [[LOOP]]:224; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]225; CHECK-NEXT: call void @foo(i32 20)226; CHECK-NEXT: [[C:%.*]] = call i1 @cond()227; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LATCH]]228; CHECK: [[THEN]]:229; CHECK-NEXT: call void @foo(i32 20)230; CHECK-NEXT: br label %[[LATCH]]231; CHECK: [[LATCH]]:232; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1233; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 63234; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT_PEEL_BEGIN:.*]], !llvm.loop [[LOOP4:![0-9]+]]235; CHECK: [[EXIT_PEEL_BEGIN]]:236; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], %[[LATCH]] ]237; CHECK-NEXT: br label %[[LOOP_PEEL:.*]]238; CHECK: [[LOOP_PEEL]]:239; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp eq i64 [[IV_NEXT_LCSSA]], 63240; CHECK-NEXT: [[COND_PEEL:%.*]] = select i1 [[CMP_PEEL]], i32 10, i32 20241; CHECK-NEXT: call void @foo(i32 [[COND_PEEL]])242; CHECK-NEXT: [[C_PEEL:%.*]] = call i1 @cond()243; CHECK-NEXT: br i1 [[C_PEEL]], label %[[THEN_PEEL:.*]], label %[[LATCH_PEEL:.*]]244; CHECK: [[THEN_PEEL]]:245; CHECK-NEXT: call void @foo(i32 [[COND_PEEL]])246; CHECK-NEXT: br label %[[LATCH_PEEL]]247; CHECK: [[LATCH_PEEL]]:248; CHECK-NEXT: [[IV_NEXT_PEEL:%.*]] = add i64 [[IV_NEXT_LCSSA]], 1249; CHECK-NEXT: [[EC_PEEL:%.*]] = icmp ne i64 [[IV_NEXT_PEEL]], 64250; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[EXIT_PEEL_NEXT:.*]], label %[[EXIT_PEEL_NEXT]]251; CHECK: [[EXIT_PEEL_NEXT]]:252; CHECK-NEXT: br label %[[LOOP_PEEL_NEXT:.*]]253; CHECK: [[LOOP_PEEL_NEXT]]:254; CHECK-NEXT: br label %[[EXIT:.*]]255; CHECK: [[EXIT]]:256; CHECK-NEXT: ret i64 [[IV_NEXT_LCSSA]]257;258entry:259 br label %loop260 261loop:262 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]263 %cmp = icmp eq i64 %iv, 63264 %cond = select i1 %cmp, i32 10, i32 20265 call void @foo(i32 %cond)266 %c = call i1 @cond()267 br i1 %c, label %then, label %latch268 269then:270 call void @foo(i32 %cond)271 br label %latch272 273latch:274 %iv.next = add i64 %iv, 1275 %ec = icmp ne i64 %iv.next, 64276 br i1 %ec, label %loop, label %exit277 278exit:279 ret i64 %iv280}281 282define i64 @peel_multi_exit_loop_iv_step_1() {283; CHECK-LABEL: define i64 @peel_multi_exit_loop_iv_step_1() {284; CHECK-NEXT: [[ENTRY:.*]]:285; CHECK-NEXT: br label %[[LOOP:.*]]286; CHECK: [[LOOP]]:287; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]288; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], 63289; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20290; CHECK-NEXT: call void @foo(i32 [[COND]])291; CHECK-NEXT: [[C:%.*]] = call i1 @cond()292; CHECK-NEXT: br i1 [[C]], label %[[EXIT:.*]], label %[[LATCH]]293; CHECK: [[LATCH]]:294; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1295; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 64296; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT]]297; CHECK: [[EXIT]]:298; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LATCH]] ], [ [[IV]], %[[LOOP]] ]299; CHECK-NEXT: ret i64 [[IV_LCSSA]]300;301entry:302 br label %loop303 304loop:305 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]306 %cmp = icmp eq i64 %iv, 63307 %cond = select i1 %cmp, i32 10, i32 20308 call void @foo(i32 %cond)309 %c = call i1 @cond()310 br i1 %c, label %exit, label %latch311 312latch:313 %iv.next = add i64 %iv, 1314 %ec = icmp ne i64 %iv.next, 64315 br i1 %ec, label %loop, label %exit316 317exit:318 ret i64 %iv319}320 321define i64 @peel_single_block_loop_iv_step_1_btc_0() {322; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_btc_0() {323; CHECK-NEXT: [[ENTRY:.*]]:324; CHECK-NEXT: br label %[[LOOP:.*]]325; CHECK: [[LOOP]]:326; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]327; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV]], 0328; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 10, i32 20329; CHECK-NEXT: call void @foo(i32 [[COND]])330; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1331; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 1332; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]333; CHECK: [[EXIT]]:334; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]335; CHECK-NEXT: ret i64 [[IV_LCSSA]]336;337entry:338 br label %loop339 340loop:341 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]342 %cmp = icmp eq i64 %iv, 0343 %cond = select i1 %cmp, i32 10, i32 20344 call void @foo(i32 %cond)345 %iv.next = add i64 %iv, 1346 %ec = icmp ne i64 %iv.next, 1347 br i1 %ec, label %loop, label %exit348 349exit:350 ret i64 %iv351}352 353define i64 @peel_single_block_loop_iv_step_1_btc_1() {354; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_btc_1() {355; CHECK-NEXT: [[ENTRY:.*]]:356; CHECK-NEXT: br label %[[LOOP:.*]]357; CHECK: [[LOOP]]:358; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT1:%.*]], %[[LOOP]] ]359; CHECK-NEXT: call void @foo(i32 20)360; CHECK-NEXT: [[IV_NEXT1]] = add nuw nsw i64 [[IV1]], 1361; CHECK-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT_PEEL_BEGIN:.*]], !llvm.loop [[LOOP5:![0-9]+]]362; CHECK: [[EXIT_PEEL_BEGIN]]:363; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT1]], %[[LOOP]] ]364; CHECK-NEXT: br label %[[LOOP_PEEL:.*]]365; CHECK: [[LOOP_PEEL]]:366; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV]], 1367; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 10, i32 20368; CHECK-NEXT: call void @foo(i32 [[COND]])369; CHECK-NEXT: [[IV_NEXT:%.*]] = add i64 [[IV]], 1370; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 2371; CHECK-NEXT: br i1 [[EC]], label %[[EXIT_PEEL_NEXT:.*]], label %[[EXIT_PEEL_NEXT]]372; CHECK: [[EXIT_PEEL_NEXT]]:373; CHECK-NEXT: br label %[[LOOP_PEEL_NEXT:.*]]374; CHECK: [[LOOP_PEEL_NEXT]]:375; CHECK-NEXT: br label %[[EXIT:.*]]376; CHECK: [[EXIT]]:377; CHECK-NEXT: ret i64 [[IV]]378;379entry:380 br label %loop381 382loop:383 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]384 %cmp = icmp eq i64 %iv, 1385 %cond = select i1 %cmp, i32 10, i32 20386 call void @foo(i32 %cond)387 %iv.next = add i64 %iv, 1388 %ec = icmp ne i64 %iv.next, 2389 br i1 %ec, label %loop, label %exit390 391exit:392 ret i64 %iv393}394 395define i64 @peel_single_block_loop_iv_step_neg_1() {396; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_neg_1() {397; CHECK-NEXT: [[ENTRY:.*]]:398; CHECK-NEXT: br label %[[LOOP:.*]]399; CHECK: [[LOOP]]:400; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 64, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]401; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], 1402; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20403; CHECK-NEXT: call void @foo(i32 [[COND]])404; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1405; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 0406; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]407; CHECK: [[EXIT]]:408; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]409; CHECK-NEXT: ret i64 [[IV_LCSSA]]410;411entry:412 br label %loop413 414loop:415 %iv = phi i64 [ 64, %entry ], [ %iv.next, %loop ]416 %cmp = icmp eq i64 %iv, 1417 %cond = select i1 %cmp, i32 10, i32 20418 call void @foo(i32 %cond)419 %iv.next = add i64 %iv, -1420 %ec = icmp ne i64 %iv.next, 0421 br i1 %ec, label %loop, label %exit422 423exit:424 ret i64 %iv425}426 427define i64 @peel_single_block_loop_iv_step_2() {428; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_2() {429; CHECK-NEXT: [[ENTRY:.*]]:430; CHECK-NEXT: br label %[[LOOP:.*]]431; CHECK: [[LOOP]]:432; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]433; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], 62434; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20435; CHECK-NEXT: call void @foo(i32 [[COND]])436; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2437; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], 64438; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]439; CHECK: [[EXIT]]:440; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]441; CHECK-NEXT: ret i64 [[IV_LCSSA]]442;443entry:444 br label %loop445 446loop:447 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]448 %cmp = icmp eq i64 %iv, 62449 %cond = select i1 %cmp, i32 10, i32 20450 call void @foo(i32 %cond)451 %iv.next = add i64 %iv, 2452 %ec = icmp ne i64 %iv.next, 64453 br i1 %ec, label %loop, label %exit454 455exit:456 ret i64 %iv457}458 459define i32 @peel_loop_with_branch_and_phi_uses(ptr %x, i1 %c) {460; CHECK-LABEL: define i32 @peel_loop_with_branch_and_phi_uses(461; CHECK-SAME: ptr [[X:%.*]], i1 [[C:%.*]]) {462; CHECK-NEXT: [[ENTRY:.*]]:463; CHECK-NEXT: br i1 [[C]], label %[[LOOP_HEADER_PREHEADER:.*]], label %[[EXIT:.*]]464; CHECK: [[LOOP_HEADER_PREHEADER]]:465; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]466; CHECK: [[LOOP_HEADER]]:467; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ [[IV_NEXT1:%.*]], %[[LOOP_LATCH:.*]] ], [ 0, %[[LOOP_HEADER_PREHEADER]] ]468; CHECK-NEXT: [[RED1:%.*]] = phi i32 [ [[ADD1:%.*]], %[[LOOP_LATCH]] ], [ 0, %[[LOOP_HEADER_PREHEADER]] ]469; CHECK-NEXT: br i1 false, label %[[IF_THEN:.*]], label %[[LOOP_LATCH]]470; CHECK: [[IF_THEN]]:471; CHECK-NEXT: tail call void @foo(i32 10)472; CHECK-NEXT: br label %[[LOOP_LATCH]]473; CHECK: [[LOOP_LATCH]]:474; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i32 [[IV1]]475; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[GEP_X1]], align 4476; CHECK-NEXT: [[ADD1]] = add nsw i32 [[L1]], [[RED1]]477; CHECK-NEXT: [[IV_NEXT1]] = add nuw nsw i32 [[IV1]], 1478; CHECK-NEXT: [[EC1:%.*]] = icmp ne i32 [[IV_NEXT1]], 99479; CHECK-NEXT: br i1 [[EC1]], label %[[LOOP_HEADER]], label %[[LOOPEXIT_PEEL_BEGIN:.*]], !llvm.loop [[LOOP6:![0-9]+]]480; CHECK: [[LOOPEXIT_PEEL_BEGIN]]:481; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT1]], %[[LOOP_LATCH]] ]482; CHECK-NEXT: [[RED:%.*]] = phi i32 [ [[ADD1]], %[[LOOP_LATCH]] ]483; CHECK-NEXT: br label %[[LOOP_HEADER_PEEL:.*]]484; CHECK: [[LOOP_HEADER_PEEL]]:485; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[IV]], 99486; CHECK-NEXT: br i1 [[CMP1]], label %[[IF_THEN_PEEL:.*]], label %[[LOOP_LATCH_PEEL:.*]]487; CHECK: [[IF_THEN_PEEL]]:488; CHECK-NEXT: tail call void @foo(i32 10)489; CHECK-NEXT: br label %[[LOOP_LATCH_PEEL]]490; CHECK: [[LOOP_LATCH_PEEL]]:491; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i32 [[IV]]492; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP_X]], align 4493; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[L]], [[RED]]494; CHECK-NEXT: [[IV_NEXT:%.*]] = add nuw nsw i32 [[IV]], 1495; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[IV_NEXT]], 100496; CHECK-NEXT: br i1 [[EC]], label %[[LOOPEXIT_PEEL_NEXT:.*]], label %[[LOOPEXIT_PEEL_NEXT]]497; CHECK: [[LOOPEXIT_PEEL_NEXT]]:498; CHECK-NEXT: br label %[[LOOP_HEADER_PEEL_NEXT:.*]]499; CHECK: [[LOOP_HEADER_PEEL_NEXT]]:500; CHECK-NEXT: br label %[[LOOPEXIT:.*]]501; CHECK: [[LOOPEXIT]]:502; CHECK-NEXT: br label %[[EXIT]]503; CHECK: [[EXIT]]:504; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[ADD]], %[[LOOPEXIT]] ]505; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]506;507entry:508 br i1 %c, label %loop.header, label %exit509 510loop.header:511 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]512 %red = phi i32 [ 0, %entry ], [ %add, %loop.latch ]513 %cmp1 = icmp eq i32 %iv, 99514 br i1 %cmp1, label %if.then, label %loop.latch515 516if.then:517 tail call void @foo(i32 10)518 br label %loop.latch519 520loop.latch:521 %gep.x = getelementptr inbounds nuw i32, ptr %x, i32 %iv522 %l = load i32, ptr %gep.x, align 4523 %add = add nsw i32 %l, %red524 %iv.next = add nuw nsw i32 %iv, 1525 %ec = icmp ne i32 %iv.next, 100526 br i1 %ec, label %loop.header, label %loopexit527 528loopexit:529 %add.lcssa = phi i32 [ %add, %loop.latch ]530 br label %exit531 532exit:533 %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %loopexit ]534 ret i32 %sum.0.lcssa535}536 537define i64 @peel_multi_exit_multi_latch_loop_iv_step_1(i64 %N) {538; CHECK-LABEL: define i64 @peel_multi_exit_multi_latch_loop_iv_step_1(539; CHECK-SAME: i64 [[N:%.*]]) {540; CHECK-NEXT: [[ENTRY:.*]]:541; CHECK-NEXT: br label %[[LOOP:.*]]542; CHECK: [[LOOP]]:543; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_BE:%.*]], %[[LOOP_BACKEDGE:.*]] ]544; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV]], 63545; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 10, i32 20546; CHECK-NEXT: call void @foo(i32 [[COND]])547; CHECK-NEXT: [[C_1:%.*]] = icmp eq i64 [[IV]], [[N]]548; CHECK-NEXT: br i1 [[C_1]], label %[[THEN:.*]], label %[[ELSE:.*]]549; CHECK: [[THEN]]:550; CHECK-NEXT: call void @foo(i32 20)551; CHECK-NEXT: [[IV_NEXT_1:%.*]] = add i64 [[IV]], 1552; CHECK-NEXT: [[EC_1:%.*]] = icmp ne i64 [[IV_NEXT_1]], 64553; CHECK-NEXT: br i1 [[EC_1]], label %[[EXIT:.*]], label %[[LOOP_BACKEDGE]]554; CHECK: [[LOOP_BACKEDGE]]:555; CHECK-NEXT: [[IV_BE]] = phi i64 [ [[IV_NEXT_1]], %[[THEN]] ], [ [[IV_NEXT_2:%.*]], %[[ELSE]] ]556; CHECK-NEXT: br label %[[LOOP]]557; CHECK: [[ELSE]]:558; CHECK-NEXT: call void @foo(i32 10)559; CHECK-NEXT: [[IV_NEXT_2]] = add i64 [[IV]], 1560; CHECK-NEXT: [[EC_2:%.*]] = icmp ne i64 [[IV_NEXT_2]], 64561; CHECK-NEXT: br i1 [[EC_2]], label %[[LOOP_BACKEDGE]], label %[[EXIT]]562; CHECK: [[EXIT]]:563; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[ELSE]] ], [ [[IV]], %[[THEN]] ]564; CHECK-NEXT: ret i64 [[IV_LCSSA]]565;566entry:567 br label %loop568 569loop:570 %iv = phi i64 [ 0, %entry ], [ %iv.next.1, %then ], [ %iv.next.2, %else ]571 %cmp = icmp eq i64 %iv, 63572 %cond = select i1 %cmp, i32 10, i32 20573 call void @foo(i32 %cond)574 %c.1 = icmp eq i64 %iv, %N575 br i1 %c.1, label %then, label %else576 577then:578 call void @foo(i32 20)579 %iv.next.1 = add i64 %iv, 1580 %ec.1 = icmp ne i64 %iv.next.1, 64581 br i1 %ec.1, label %exit, label %loop582 583else:584 call void @foo(i32 10)585 %iv.next.2 = add i64 %iv, 1586 %ec.2 = icmp ne i64 %iv.next.2, 64587 br i1 %ec.2, label %loop, label %exit588 589exit:590 ret i64 %iv591}592 593; Test for https://github.com/llvm/llvm-project/issues/140444.594define void @exit_condition_has_other_loop_users() {595; CHECK-LABEL: define void @exit_condition_has_other_loop_users() {596; CHECK-NEXT: [[ENTRY:.*]]:597; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]598; CHECK: [[LOOP_HEADER]]:599; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i16 [ 0, %[[ENTRY]] ], [ [[IV_NEXT_PEEL:%.*]], %[[LOOP_LATCH:.*]] ]600; CHECK-NEXT: [[IV_NEXT_PEEL]] = add i16 [[IV_NEXT_LCSSA]], 1601; CHECK-NEXT: [[EC_PEEL:%.*]] = icmp eq i16 [[IV_NEXT_LCSSA]], 100602; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[LOOP_LATCH]], label %[[THEN:.*]]603; CHECK: [[THEN]]:604; CHECK-NEXT: call void @foo(i32 10)605; CHECK-NEXT: br label %[[LOOP_LATCH]]606; CHECK: [[LOOP_LATCH]]:607; CHECK-NEXT: call void @foo(i32 20)608; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[EXIT:.*]], label %[[LOOP_HEADER]]609; CHECK: [[EXIT]]:610; CHECK-NEXT: ret void611;612entry:613 br label %loop.header614 615loop.header:616 %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop.latch ]617 %iv.next = add i16 %iv, 1618 %ec = icmp eq i16 %iv, 100619 br i1 %ec, label %loop.latch, label %then620 621then:622 call void @foo(i32 10)623 br label %loop.latch624 625loop.latch:626 call void @foo(i32 20)627 br i1 %ec, label %exit, label %loop.header628 629exit:630 ret void631}632 633declare void @foo(i32)634declare i1 @cond()635;.636; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]]}637; CHECK: [[META1]] = !{!"llvm.loop.peeled.count", i32 1}638; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META1]]}639; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]]}640; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]]}641; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]]}642; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]]}643;.644