brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.8 KiB · bc63f79 Raw
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