501 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes='loop(indvars),loop-unroll' -verify-loop-info | FileCheck %s3;4target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"5 6; Unit tests for loop unrolling using ScalarEvolution to compute trip counts.7;8; Indvars is run first to generate an "old" SCEV result. Some unit9; tests may check that SCEV is properly invalidated between passes.10 11; Completely unroll loops without a canonical IV.12define i32 @sansCanonical(ptr %base) nounwind {13; CHECK-LABEL: @sansCanonical(14; CHECK-NEXT: entry:15; CHECK-NEXT: br label [[WHILE_BODY:%.*]]16; CHECK: while.body:17; CHECK-NEXT: [[ADR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 918; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[ADR]], align 819; CHECK-NEXT: [[ADR_1:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 820; CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[ADR_1]], align 821; CHECK-NEXT: [[SUM_NEXT_1:%.*]] = add i32 [[TMP]], [[TMP_1]]22; CHECK-NEXT: [[ADR_2:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 723; CHECK-NEXT: [[TMP_2:%.*]] = load i32, ptr [[ADR_2]], align 824; CHECK-NEXT: [[SUM_NEXT_2:%.*]] = add i32 [[SUM_NEXT_1]], [[TMP_2]]25; CHECK-NEXT: [[ADR_3:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 626; CHECK-NEXT: [[TMP_3:%.*]] = load i32, ptr [[ADR_3]], align 827; CHECK-NEXT: [[SUM_NEXT_3:%.*]] = add i32 [[SUM_NEXT_2]], [[TMP_3]]28; CHECK-NEXT: [[ADR_4:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 529; CHECK-NEXT: [[TMP_4:%.*]] = load i32, ptr [[ADR_4]], align 830; CHECK-NEXT: [[SUM_NEXT_4:%.*]] = add i32 [[SUM_NEXT_3]], [[TMP_4]]31; CHECK-NEXT: [[ADR_5:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 432; CHECK-NEXT: [[TMP_5:%.*]] = load i32, ptr [[ADR_5]], align 833; CHECK-NEXT: [[SUM_NEXT_5:%.*]] = add i32 [[SUM_NEXT_4]], [[TMP_5]]34; CHECK-NEXT: [[ADR_6:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 335; CHECK-NEXT: [[TMP_6:%.*]] = load i32, ptr [[ADR_6]], align 836; CHECK-NEXT: [[SUM_NEXT_6:%.*]] = add i32 [[SUM_NEXT_5]], [[TMP_6]]37; CHECK-NEXT: [[ADR_7:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 238; CHECK-NEXT: [[TMP_7:%.*]] = load i32, ptr [[ADR_7]], align 839; CHECK-NEXT: [[SUM_NEXT_7:%.*]] = add i32 [[SUM_NEXT_6]], [[TMP_7]]40; CHECK-NEXT: [[ADR_8:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 141; CHECK-NEXT: [[TMP_8:%.*]] = load i32, ptr [[ADR_8]], align 842; CHECK-NEXT: [[SUM_NEXT_8:%.*]] = add i32 [[SUM_NEXT_7]], [[TMP_8]]43; CHECK-NEXT: ret i32 [[SUM_NEXT_8]]44;45entry:46 br label %while.body47 48while.body:49 %iv = phi i64 [ 10, %entry ], [ %iv.next, %while.body ]50 %sum = phi i32 [ 0, %entry ], [ %sum.next, %while.body ]51 %iv.next = add i64 %iv, -152 %adr = getelementptr inbounds i32, ptr %base, i64 %iv.next53 %tmp = load i32, ptr %adr, align 854 %sum.next = add i32 %sum, %tmp55 %iv.narrow = trunc i64 %iv.next to i3256 %cmp.i65 = icmp sgt i32 %iv.narrow, 057 br i1 %cmp.i65, label %while.body, label %exit58 59exit:60 ret i32 %sum61}62 63; SCEV unrolling properly handles loops with multiple exits. In this64; case, the computed trip count based on a canonical IV is *not* for a65; latch block.66define i64 @earlyLoopTest(ptr %base) nounwind {67; CHECK-LABEL: @earlyLoopTest(68; CHECK-NEXT: entry:69; CHECK-NEXT: br label [[LOOP:%.*]]70; CHECK: loop:71; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[BASE:%.*]], align 872; CHECK-NEXT: br label [[TAIL:%.*]]73; CHECK: tail:74; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[VAL]], 075; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_1:%.*]], label [[EXIT2:%.*]]76; CHECK: loop.1:77; CHECK-NEXT: [[ADR_1:%.*]] = getelementptr i64, ptr [[BASE]], i64 178; CHECK-NEXT: [[VAL_1:%.*]] = load i64, ptr [[ADR_1]], align 879; CHECK-NEXT: [[S_NEXT_1:%.*]] = add i64 [[VAL]], [[VAL_1]]80; CHECK-NEXT: br label [[TAIL_1:%.*]]81; CHECK: tail.1:82; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ne i64 [[VAL_1]], 083; CHECK-NEXT: br i1 [[CMP2_1]], label [[LOOP_2:%.*]], label [[EXIT2]]84; CHECK: loop.2:85; CHECK-NEXT: [[ADR_2:%.*]] = getelementptr i64, ptr [[BASE]], i64 286; CHECK-NEXT: [[VAL_2:%.*]] = load i64, ptr [[ADR_2]], align 887; CHECK-NEXT: [[S_NEXT_2:%.*]] = add i64 [[S_NEXT_1]], [[VAL_2]]88; CHECK-NEXT: br label [[TAIL_2:%.*]]89; CHECK: tail.2:90; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ne i64 [[VAL_2]], 091; CHECK-NEXT: br i1 [[CMP2_2]], label [[LOOP_3:%.*]], label [[EXIT2]]92; CHECK: loop.3:93; CHECK-NEXT: [[ADR_3:%.*]] = getelementptr i64, ptr [[BASE]], i64 394; CHECK-NEXT: [[VAL_3:%.*]] = load i64, ptr [[ADR_3]], align 895; CHECK-NEXT: [[S_NEXT_3:%.*]] = add i64 [[S_NEXT_2]], [[VAL_3]]96; CHECK-NEXT: br i1 false, label [[TAIL_3:%.*]], label [[EXIT1:%.*]]97; CHECK: tail.3:98; CHECK-NEXT: br label [[EXIT2]]99; CHECK: exit1:100; CHECK-NEXT: [[S_LCSSA:%.*]] = phi i64 [ [[S_NEXT_2]], [[LOOP_3]] ]101; CHECK-NEXT: ret i64 [[S_LCSSA]]102; CHECK: exit2:103; CHECK-NEXT: [[S_NEXT_LCSSA1:%.*]] = phi i64 [ [[VAL]], [[TAIL]] ], [ [[S_NEXT_1]], [[TAIL_1]] ], [ [[S_NEXT_2]], [[TAIL_2]] ], [ [[S_NEXT_3]], [[TAIL_3]] ]104; CHECK-NEXT: ret i64 [[S_NEXT_LCSSA1]]105;106entry:107 br label %loop108 109loop:110 %iv = phi i64 [ 0, %entry ], [ %inc, %tail ]111 %s = phi i64 [ 0, %entry ], [ %s.next, %tail ]112 %adr = getelementptr i64, ptr %base, i64 %iv113 %val = load i64, ptr %adr114 %s.next = add i64 %s, %val115 %inc = add i64 %iv, 1116 %cmp = icmp ne i64 %inc, 4117 br i1 %cmp, label %tail, label %exit1118 119tail:120 %cmp2 = icmp ne i64 %val, 0121 br i1 %cmp2, label %loop, label %exit2122 123exit1:124 ret i64 %s125 126exit2:127 ret i64 %s.next128}129 130; SCEV properly unrolls multi-exit loops.131define i32 @multiExit(ptr %base) nounwind {132; CHECK-LABEL: @multiExit(133; CHECK-NEXT: entry:134; CHECK-NEXT: br label [[L1:%.*]]135; CHECK: l1:136; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[BASE:%.*]], align 4137; CHECK-NEXT: br i1 false, label [[L2:%.*]], label [[EXIT1:%.*]]138; CHECK: l2:139; CHECK-NEXT: ret i32 [[VAL]]140; CHECK: exit1:141; CHECK-NEXT: ret i32 1142;143entry:144 br label %l1145l1:146 %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l2 ]147 %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l2 ]148 %inc1 = add i32 %iv1, 1149 %inc2 = add i32 %iv2, 1150 %adr = getelementptr i32, ptr %base, i32 %iv1151 %val = load i32, ptr %adr152 %cmp1 = icmp slt i32 %iv1, 5153 br i1 %cmp1, label %l2, label %exit1154l2:155 %cmp2 = icmp slt i32 %iv2, 10156 br i1 %cmp2, label %l1, label %exit2157exit1:158 ret i32 1159exit2:160 ret i32 %val161}162 163 164; SCEV can unroll a multi-exit loops even if the latch block has no165; known trip count, but an early exit has a known trip count. In this166; case we must be careful not to optimize the latch branch away.167define i32 @multiExitIncomplete(ptr %base) nounwind {168; CHECK-LABEL: @multiExitIncomplete(169; CHECK-NEXT: entry:170; CHECK-NEXT: br label [[L1:%.*]]171; CHECK: l1:172; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[BASE:%.*]], align 4173; CHECK-NEXT: br label [[L2:%.*]]174; CHECK: l2:175; CHECK-NEXT: br label [[L3:%.*]]176; CHECK: l3:177; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[VAL]], 0178; CHECK-NEXT: br i1 [[CMP3]], label [[L1_1:%.*]], label [[EXIT3:%.*]]179; CHECK: l1.1:180; CHECK-NEXT: [[ADR_1:%.*]] = getelementptr i32, ptr [[BASE]], i32 1181; CHECK-NEXT: [[VAL_1:%.*]] = load i32, ptr [[ADR_1]], align 4182; CHECK-NEXT: br label [[L2_1:%.*]]183; CHECK: l2.1:184; CHECK-NEXT: br label [[L3_1:%.*]]185; CHECK: l3.1:186; CHECK-NEXT: [[CMP3_1:%.*]] = icmp ne i32 [[VAL_1]], 0187; CHECK-NEXT: br i1 [[CMP3_1]], label [[L1_2:%.*]], label [[EXIT3]]188; CHECK: l1.2:189; CHECK-NEXT: [[ADR_2:%.*]] = getelementptr i32, ptr [[BASE]], i32 2190; CHECK-NEXT: [[VAL_2:%.*]] = load i32, ptr [[ADR_2]], align 4191; CHECK-NEXT: br label [[L2_2:%.*]]192; CHECK: l2.2:193; CHECK-NEXT: br label [[L3_2:%.*]]194; CHECK: l3.2:195; CHECK-NEXT: [[CMP3_2:%.*]] = icmp ne i32 [[VAL_2]], 0196; CHECK-NEXT: br i1 [[CMP3_2]], label [[L1_3:%.*]], label [[EXIT3]]197; CHECK: l1.3:198; CHECK-NEXT: [[ADR_3:%.*]] = getelementptr i32, ptr [[BASE]], i32 3199; CHECK-NEXT: [[VAL_3:%.*]] = load i32, ptr [[ADR_3]], align 4200; CHECK-NEXT: br label [[L2_3:%.*]]201; CHECK: l2.3:202; CHECK-NEXT: br label [[L3_3:%.*]]203; CHECK: l3.3:204; CHECK-NEXT: [[CMP3_3:%.*]] = icmp ne i32 [[VAL_3]], 0205; CHECK-NEXT: br i1 [[CMP3_3]], label [[L1_4:%.*]], label [[EXIT3]]206; CHECK: l1.4:207; CHECK-NEXT: [[ADR_4:%.*]] = getelementptr i32, ptr [[BASE]], i32 4208; CHECK-NEXT: [[VAL_4:%.*]] = load i32, ptr [[ADR_4]], align 4209; CHECK-NEXT: br label [[L2_4:%.*]]210; CHECK: l2.4:211; CHECK-NEXT: br label [[L3_4:%.*]]212; CHECK: l3.4:213; CHECK-NEXT: [[CMP3_4:%.*]] = icmp ne i32 [[VAL_4]], 0214; CHECK-NEXT: br i1 [[CMP3_4]], label [[L1_5:%.*]], label [[EXIT3]]215; CHECK: l1.5:216; CHECK-NEXT: br i1 false, label [[L2_5:%.*]], label [[EXIT1:%.*]]217; CHECK: l2.5:218; CHECK-NEXT: br i1 true, label [[L3_5:%.*]], label [[EXIT2:%.*]]219; CHECK: l3.5:220; CHECK-NEXT: br label [[EXIT3]]221; CHECK: exit1:222; CHECK-NEXT: ret i32 1223; CHECK: exit2:224; CHECK-NEXT: ret i32 2225; CHECK: exit3:226; CHECK-NEXT: ret i32 3227;228entry:229 br label %l1230l1:231 %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l3 ]232 %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l3 ]233 %inc1 = add i32 %iv1, 1234 %inc2 = add i32 %iv2, 1235 %adr = getelementptr i32, ptr %base, i32 %iv1236 %val = load i32, ptr %adr237 %cmp1 = icmp slt i32 %iv1, 5238 br i1 %cmp1, label %l2, label %exit1239l2:240 %cmp2 = icmp slt i32 %iv2, 10241 br i1 %cmp2, label %l3, label %exit2242l3:243 %cmp3 = icmp ne i32 %val, 0244 br i1 %cmp3, label %l1, label %exit3245 246exit1:247 ret i32 1248exit2:249 ret i32 2250exit3:251 ret i32 3252}253 254; When loop unroll merges a loop exit with one of its parent loop's255; exits, SCEV must forget its ExitNotTaken info.256define void @nestedUnroll() nounwind {257; CHECK-LABEL: @nestedUnroll(258; CHECK-NEXT: entry:259; CHECK-NEXT: br label [[FOR_INC:%.*]]260; CHECK: for.inc:261; CHECK-NEXT: br label [[FOR_BODY38:%.*]]262; CHECK: for.body38:263; CHECK-NEXT: br label [[FOR_BODY43:%.*]]264; CHECK: for.body43:265; CHECK-NEXT: br label [[FOR_BODY87:%.*]]266; CHECK: for.body87:267; CHECK-NEXT: br label [[FOR_BODY87]]268;269entry:270 br label %for.inc271 272for.inc:273 br i1 false, label %for.inc, label %for.body38.preheader274 275for.body38.preheader:276 br label %for.body38277 278for.body38:279 %i.113 = phi i32 [ %inc76, %for.inc74 ], [ 0, %for.body38.preheader ]280 %mul48 = mul nsw i32 %i.113, 6281 br label %for.body43282 283for.body43:284 %j.011 = phi i32 [ 0, %for.body38 ], [ %inc72, %for.body43 ]285 %add49 = add nsw i32 %j.011, %mul48286 %sh_prom50 = zext i32 %add49 to i64287 %inc72 = add nsw i32 %j.011, 1288 br i1 false, label %for.body43, label %for.inc74289 290for.inc74:291 %inc76 = add nsw i32 %i.113, 1292 br i1 false, label %for.body38, label %for.body87.preheader293 294for.body87.preheader:295 br label %for.body87296 297for.body87:298 br label %for.body87299}300 301; PR16130: clang produces incorrect code with loop/expression at -O2302; rdar:14036816 loop-unroll makes assumptions about undefined behavior303;304; The loop latch is assumed to exit after the first iteration because305; of the induction variable's NSW flag. However, the loop latch's306; equality test is skipped and the loop exits after the second307; iteration via the early exit. So loop unrolling cannot assume that308; the loop latch's exit count of zero is an upper bound on the number309; of iterations.310define void @nsw_latch(ptr %a) nounwind {311; CHECK-LABEL: @nsw_latch(312; CHECK-NEXT: entry:313; CHECK-NEXT: br label [[FOR_BODY:%.*]]314; CHECK: for.body:315; CHECK-NEXT: br label [[FOR_COND:%.*]]316; CHECK: for.cond:317; CHECK-NEXT: br i1 false, label [[RETURN:%.*]], label [[FOR_BODY_1:%.*]]318; CHECK: for.body.1:319; CHECK-NEXT: br i1 false, label [[FOR_COND_1:%.*]], label [[RETURN]]320; CHECK: for.cond.1:321; CHECK-NEXT: br label [[RETURN]]322; CHECK: return:323; CHECK-NEXT: [[B_03_LCSSA:%.*]] = phi i32 [ 0, [[FOR_COND]] ], [ 8, [[FOR_BODY_1]] ], [ 0, [[FOR_COND_1]] ]324; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[FOR_COND]] ], [ 1, [[FOR_BODY_1]] ], [ 0, [[FOR_COND_1]] ]325; CHECK-NEXT: store i32 [[B_03_LCSSA]], ptr [[A:%.*]], align 4326; CHECK-NEXT: ret void327;328entry:329 br label %for.body330 331for.body: ; preds = %for.cond, %entry332 %b.03 = phi i32 [ 0, %entry ], [ %add, %for.cond ]333 %tobool = icmp eq i32 %b.03, 0334 %add = add nsw i32 %b.03, 8335 br i1 %tobool, label %for.cond, label %return336 337for.cond: ; preds = %for.body338 %cmp = icmp eq i32 %add, 13339 br i1 %cmp, label %return, label %for.body340 341return: ; preds = %for.body, %for.cond342 %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ %b.03, %for.cond ]343 %retval.0 = phi i32 [ 1, %for.body ], [ 0, %for.cond ]344 store i32 %b.03.lcssa, ptr %a, align 4345 ret void346}347 348; Test case for PR56044. Check that SCEVs for exit phis are properly invalidated.349define i32 @test_pr56044(ptr %src, i32 %a) {350; CHECK-LABEL: @test_pr56044(351; CHECK-NEXT: entry:352; CHECK-NEXT: br label [[LOOP_1_PEEL_BEGIN:%.*]]353; CHECK: loop.1.peel.begin:354; CHECK-NEXT: br label [[LOOP_1_PEEL:%.*]]355; CHECK: loop.1.peel:356; CHECK-NEXT: call void @fn(i32 5)357; CHECK-NEXT: [[L_PEEL:%.*]] = load i64, ptr [[SRC:%.*]], align 8358; CHECK-NEXT: [[ADD_PEEL:%.*]] = add i64 [[L_PEEL]], [[L_PEEL]]359; CHECK-NEXT: [[EC_1_PEEL:%.*]] = icmp sgt i32 [[A:%.*]], 4360; CHECK-NEXT: br i1 [[EC_1_PEEL]], label [[MID:%.*]], label [[LOOP_1_PEEL_NEXT:%.*]]361; CHECK: loop.1.peel.next:362; CHECK-NEXT: br label [[LOOP_1_PEEL_NEXT1:%.*]]363; CHECK: loop.1.peel.next1:364; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]]365; CHECK: entry.peel.newph:366; CHECK-NEXT: br label [[LOOP_1:%.*]]367; CHECK: loop.1:368; CHECK-NEXT: call void @fn(i32 18)369; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[SRC]], align 8370; CHECK-NEXT: [[ADD:%.*]] = add i64 [[L]], [[L]]371; CHECK-NEXT: [[EC_1:%.*]] = icmp sgt i32 [[A]], 4372; CHECK-NEXT: br i1 [[EC_1]], label [[MID_LOOPEXIT:%.*]], label [[LOOP_1]], !llvm.loop [[LOOP0:![0-9]+]]373; CHECK: mid.loopexit:374; CHECK-NEXT: [[LCSSA_1_PH:%.*]] = phi i64 [ [[ADD]], [[LOOP_1]] ]375; CHECK-NEXT: br label [[MID]]376; CHECK: mid:377; CHECK-NEXT: [[LCSSA_1:%.*]] = phi i64 [ [[ADD_PEEL]], [[LOOP_1_PEEL]] ], [ [[LCSSA_1_PH]], [[MID_LOOPEXIT]] ]378; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[LCSSA_1]] to i32379; CHECK-NEXT: [[ADD_2:%.*]] = sub i32 [[A]], [[TRUNC]]380; CHECK-NEXT: br label [[LOOP_2_PEEL_BEGIN:%.*]]381; CHECK: loop.2.peel.begin:382; CHECK-NEXT: br label [[LOOP_2_PEEL:%.*]]383; CHECK: loop.2.peel:384; CHECK-NEXT: [[IV_2_NEXT_PEEL:%.*]] = add i32 0, [[ADD_2]]385; CHECK-NEXT: [[IV_1_NEXT_PEEL:%.*]] = add nuw nsw i32 0, 1386; CHECK-NEXT: [[EC_2_PEEL:%.*]] = icmp ne i32 [[IV_1_NEXT_PEEL]], 12345387; CHECK-NEXT: br i1 [[EC_2_PEEL]], label [[LOOP_2_PEEL_NEXT:%.*]], label [[EXIT:%.*]]388; CHECK: loop.2.peel.next:389; CHECK-NEXT: br label [[LOOP_2_PEEL_NEXT2:%.*]]390; CHECK: loop.2.peel.next2:391; CHECK-NEXT: br label [[MID_PEEL_NEWPH:%.*]]392; CHECK: mid.peel.newph:393; CHECK-NEXT: br label [[LOOP_2:%.*]]394; CHECK: loop.2:395; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[IV_1_NEXT_PEEL]], [[MID_PEEL_NEWPH]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_2]] ]396; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_2_NEXT_PEEL]], [[MID_PEEL_NEWPH]] ], [ [[IV_2_NEXT:%.*]], [[LOOP_2]] ]397; CHECK-NEXT: [[IV_2_NEXT]] = add i32 2, [[IV_2]]398; CHECK-NEXT: [[IV_1_NEXT]] = add nuw nsw i32 [[IV_1]], 1399; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_1_NEXT]], 12345400; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_2]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]]401; CHECK: exit.loopexit:402; CHECK-NEXT: [[LCSSA_2_PH:%.*]] = phi i32 [ [[IV_2_NEXT]], [[LOOP_2]] ]403; CHECK-NEXT: br label [[EXIT]]404; CHECK: exit:405; CHECK-NEXT: [[LCSSA_2:%.*]] = phi i32 [ [[IV_2_NEXT_PEEL]], [[LOOP_2_PEEL]] ], [ [[LCSSA_2_PH]], [[EXIT_LOOPEXIT]] ]406; CHECK-NEXT: ret i32 [[LCSSA_2]]407;408entry:409 br label %loop.1410 411loop.1:412 %p.1 = phi i32 [ 5, %entry ], [ 18, %loop.1 ]413 call void @fn(i32 %p.1)414 %l = load i64, ptr %src, align 8415 %add = add i64 %l, %l416 %ec.1 = icmp sgt i32 %a, 4417 br i1 %ec.1, label %mid, label %loop.1418 419mid:420 %lcssa.1 = phi i64 [ %add, %loop.1 ]421 %trunc = trunc i64 %lcssa.1 to i32422 %add.2 = sub i32 %a, %trunc423 br label %loop.2424 425loop.2:426 %iv.1 = phi i32 [ 0, %mid ], [ %iv.1.next, %loop.2 ]427 %iv.2 = phi i32 [ %add.2, %mid ], [ %iv.2.next, %loop.2 ]428 %p.2 = phi i32 [ 0, %mid ], [ 2, %loop.2 ]429 %iv.2.next = add i32 %p.2, %iv.2430 %iv.1.next = add nuw nsw i32 %iv.1, 1431 %ec.2 = icmp ult i32 %iv.1.next, 12345432 br i1 %ec.2, label %loop.2, label %exit433 434exit:435 %lcssa.2 = phi i32 [ %iv.2.next, %loop.2 ]436 ret i32 %lcssa.2437}438 439declare void @fn(i32)440 441 442define void @peel_int_eq_condition(i32 %start) {443; CHECK-LABEL: @peel_int_eq_condition(444; CHECK-NEXT: entry:445; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[START:%.*]], i32 100)446; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1447; CHECK-NEXT: br label [[LOOP_PEEL_BEGIN:%.*]]448; CHECK: loop.peel.begin:449; CHECK-NEXT: br label [[LOOP_PEEL:%.*]]450; CHECK: loop.peel:451; CHECK-NEXT: [[C_0_PEEL:%.*]] = icmp eq i32 [[START]], [[START]]452; CHECK-NEXT: br i1 [[C_0_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[LOOP_LATCH_PEEL:%.*]]453; CHECK: if.then.peel:454; CHECK-NEXT: call void @fn(i32 [[START]])455; CHECK-NEXT: br label [[LOOP_LATCH_PEEL]]456; CHECK: loop.latch.peel:457; CHECK-NEXT: [[IV_NEXT_PEEL:%.*]] = add i32 [[START]], 1458; CHECK-NEXT: [[EXITCOND_PEEL:%.*]] = icmp ne i32 [[IV_NEXT_PEEL]], [[TMP0]]459; CHECK-NEXT: br i1 [[EXITCOND_PEEL]], label [[LOOP_PEEL_NEXT:%.*]], label [[EXIT:%.*]]460; CHECK: loop.peel.next:461; CHECK-NEXT: br label [[LOOP_PEEL_NEXT1:%.*]]462; CHECK: loop.peel.next1:463; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]]464; CHECK: entry.peel.newph:465; CHECK-NEXT: br label [[LOOP:%.*]]466; CHECK: loop:467; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]468; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[LOOP_LATCH]]469; CHECK: if.then:470; CHECK-NEXT: call void @fn(i32 [[IV]])471; CHECK-NEXT: br label [[LOOP_LATCH]]472; CHECK: loop.latch:473; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1474; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], [[TMP0]]475; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP3:![0-9]+]]476; CHECK: exit.loopexit:477; CHECK-NEXT: br label [[EXIT]]478; CHECK: exit:479; CHECK-NEXT: ret void480;481entry:482 br label %loop483 484loop:485 %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ]486 %c.0 = icmp eq i32 %iv, %start487 br i1 %c.0, label %if.then, label %loop.latch488 489if.then:490 call void @fn(i32 %iv)491 br label %loop.latch492 493loop.latch:494 %iv.next = add i32 %iv, 1495 %ec = icmp slt i32 %iv, 100496 br i1 %ec, label %loop, label %exit497 498exit:499 ret void500}501