Skip to content

Commit 1ae266f

Browse files
committed
[LoopUnroll] Use smallest exact trip count from any exit
This is a more general alternative/extension to D102635. Rather than handling the special case of "header exit with non-exiting latch", this unrolls against the smallest exact trip count from any exit. The latch exit is no longer treated as priviledged when it comes to full unrolling. The motivating case is in full-unroll-one-unpredictable-exit.ll. Here the header exit is an IV-based exit, while the latch exit is a data comparison. This kind of loop does not get rotated, because the latch is already exiting, and loop rotation doesn't try to distinguish IV-based/analyzable latches. Differential Revision: https://reviews.llvm.org/D102982
1 parent 558ee58 commit 1ae266f

File tree

8 files changed

+299
-151
lines changed

8 files changed

+299
-151
lines changed

llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,18 +1120,29 @@ static LoopUnrollResult tryToUnrollLoop(
11201120
return LoopUnrollResult::Unmodified;
11211121
}
11221122

1123-
// Find trip count and trip multiple if count is not available
1123+
// Find the smallest exact trip count for any exit. This is an upper bound
1124+
// on the loop trip count, but an exit at an earlier iteration is still
1125+
// possible. An unroll by the smallest exact trip count guarantees that all
1126+
// brnaches relating to at least one exit can be eliminated. This is unlike
1127+
// the max trip count, which only guarantees that the backedge can be broken.
11241128
unsigned TripCount = 0;
11251129
unsigned TripMultiple = 1;
1126-
// If there are multiple exiting blocks but one of them is the latch, use the
1127-
// latch for the trip count estimation. Otherwise insist on a single exiting
1128-
// block for the trip count estimation.
1129-
BasicBlock *ExitingBlock = L->getLoopLatch();
1130-
if (!ExitingBlock || !L->isLoopExiting(ExitingBlock))
1131-
ExitingBlock = L->getExitingBlock();
1132-
if (ExitingBlock) {
1133-
TripCount = SE.getSmallConstantTripCount(L, ExitingBlock);
1134-
TripMultiple = SE.getSmallConstantTripMultiple(L, ExitingBlock);
1130+
SmallVector<BasicBlock *, 8> ExitingBlocks;
1131+
L->getExitingBlocks(ExitingBlocks);
1132+
for (BasicBlock *ExitingBlock : ExitingBlocks)
1133+
if (unsigned TC = SE.getSmallConstantTripCount(L, ExitingBlock))
1134+
if (!TripCount || TC < TripCount)
1135+
TripCount = TripMultiple = TC;
1136+
1137+
if (!TripCount) {
1138+
// If no exact trip count is known, determine the trip multiple of either
1139+
// the loop latch or the single exiting block.
1140+
// TODO: Relax for multiple exits.
1141+
BasicBlock *ExitingBlock = L->getLoopLatch();
1142+
if (!ExitingBlock || !L->isLoopExiting(ExitingBlock))
1143+
ExitingBlock = L->getExitingBlock();
1144+
if (ExitingBlock)
1145+
TripMultiple = SE.getSmallConstantTripMultiple(L, ExitingBlock);
11351146
}
11361147

11371148
// If the loop contains a convergent operation, the prelude we'd add

llvm/test/Transforms/LoopUnroll/full-unroll-one-unpredictable-exit.ll

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,30 @@ define i1 @test_non_latch() {
8787
; CHECK-NEXT: store i64 -8661621401413125213, i64* [[A2_1]], align 8
8888
; CHECK-NEXT: br label [[LOOP:%.*]]
8989
; CHECK: loop:
90-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[START:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
91-
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV]], 2
92-
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LATCH]]
90+
; CHECK-NEXT: br label [[LATCH:%.*]]
9391
; CHECK: latch:
94-
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
95-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A1]], i64 0, i64 [[IV]]
96-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A2]], i64 0, i64 [[IV]]
92+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A1]], i64 0, i64 0
93+
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A2]], i64 0, i64 0
9794
; CHECK-NEXT: [[LOAD1:%.*]] = load i64, i64* [[GEP1]], align 8
9895
; CHECK-NEXT: [[LOAD2:%.*]] = load i64, i64* [[GEP2]], align 8
9996
; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]]
100-
; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
97+
; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP_1:%.*]], label [[EXIT:%.*]]
10198
; CHECK: exit:
102-
; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ true, [[LOOP]] ]
99+
; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ false, [[LATCH_1:%.*]] ], [ true, [[LOOP_2:%.*]] ], [ false, [[LATCH_2:%.*]] ]
103100
; CHECK-NEXT: ret i1 [[EXIT_VAL]]
101+
; CHECK: loop.1:
102+
; CHECK-NEXT: br label [[LATCH_1]]
103+
; CHECK: latch.1:
104+
; CHECK-NEXT: [[GEP1_1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A1]], i64 0, i64 1
105+
; CHECK-NEXT: [[GEP2_1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A2]], i64 0, i64 1
106+
; CHECK-NEXT: [[LOAD1_1:%.*]] = load i64, i64* [[GEP1_1]], align 8
107+
; CHECK-NEXT: [[LOAD2_1:%.*]] = load i64, i64* [[GEP2_1]], align 8
108+
; CHECK-NEXT: [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]]
109+
; CHECK-NEXT: br i1 [[EXITCOND2_1]], label [[LOOP_2]], label [[EXIT]]
110+
; CHECK: loop.2:
111+
; CHECK-NEXT: br i1 true, label [[EXIT]], label [[LATCH_2]]
112+
; CHECK: latch.2:
113+
; CHECK-NEXT: br label [[EXIT]]
104114
;
105115
start:
106116
%a1 = alloca [2 x i64], align 8

llvm/test/Transforms/LoopUnroll/multiple-exits.ll

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,24 +72,96 @@ exit:
7272
ret void
7373
}
7474

75-
; TODO: We should fully unroll this by 10, leave the unrolled latch
75+
; Fully unroll this loop by 10, but leave the unrolled latch
7676
; tests since we don't know if %N < 10, and break the backedge.
7777
define void @test2(i64 %N) {
7878
; CHECK-LABEL: @test2(
7979
; CHECK-NEXT: entry:
8080
; CHECK-NEXT: br label [[LOOP:%.*]]
8181
; CHECK: loop:
82-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
83-
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
8482
; CHECK-NEXT: call void @bar()
85-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i64 [[IV]], 10
86-
; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT:%.*]]
83+
; CHECK-NEXT: br label [[LATCH:%.*]]
8784
; CHECK: latch:
8885
; CHECK-NEXT: call void @bar()
89-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i64 [[IV]], [[N:%.*]]
90-
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT]]
86+
; CHECK-NEXT: br i1 true, label [[LOOP_1:%.*]], label [[EXIT:%.*]]
9187
; CHECK: exit:
9288
; CHECK-NEXT: ret void
89+
; CHECK: loop.1:
90+
; CHECK-NEXT: call void @bar()
91+
; CHECK-NEXT: br label [[LATCH_1:%.*]]
92+
; CHECK: latch.1:
93+
; CHECK-NEXT: call void @bar()
94+
; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ule i64 1, [[N:%.*]]
95+
; CHECK-NEXT: br i1 [[CMP2_1]], label [[LOOP_2:%.*]], label [[EXIT]]
96+
; CHECK: loop.2:
97+
; CHECK-NEXT: call void @bar()
98+
; CHECK-NEXT: br label [[LATCH_2:%.*]]
99+
; CHECK: latch.2:
100+
; CHECK-NEXT: call void @bar()
101+
; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ule i64 2, [[N]]
102+
; CHECK-NEXT: br i1 [[CMP2_2]], label [[LOOP_3:%.*]], label [[EXIT]]
103+
; CHECK: loop.3:
104+
; CHECK-NEXT: call void @bar()
105+
; CHECK-NEXT: br label [[LATCH_3:%.*]]
106+
; CHECK: latch.3:
107+
; CHECK-NEXT: call void @bar()
108+
; CHECK-NEXT: [[CMP2_3:%.*]] = icmp ule i64 3, [[N]]
109+
; CHECK-NEXT: br i1 [[CMP2_3]], label [[LOOP_4:%.*]], label [[EXIT]]
110+
; CHECK: loop.4:
111+
; CHECK-NEXT: call void @bar()
112+
; CHECK-NEXT: br label [[LATCH_4:%.*]]
113+
; CHECK: latch.4:
114+
; CHECK-NEXT: call void @bar()
115+
; CHECK-NEXT: [[CMP2_4:%.*]] = icmp ule i64 4, [[N]]
116+
; CHECK-NEXT: br i1 [[CMP2_4]], label [[LOOP_5:%.*]], label [[EXIT]]
117+
; CHECK: loop.5:
118+
; CHECK-NEXT: call void @bar()
119+
; CHECK-NEXT: br label [[LATCH_5:%.*]]
120+
; CHECK: latch.5:
121+
; CHECK-NEXT: call void @bar()
122+
; CHECK-NEXT: [[CMP2_5:%.*]] = icmp ule i64 5, [[N]]
123+
; CHECK-NEXT: br i1 [[CMP2_5]], label [[LOOP_6:%.*]], label [[EXIT]]
124+
; CHECK: loop.6:
125+
; CHECK-NEXT: call void @bar()
126+
; CHECK-NEXT: br label [[LATCH_6:%.*]]
127+
; CHECK: latch.6:
128+
; CHECK-NEXT: call void @bar()
129+
; CHECK-NEXT: [[CMP2_6:%.*]] = icmp ule i64 6, [[N]]
130+
; CHECK-NEXT: br i1 [[CMP2_6]], label [[LOOP_7:%.*]], label [[EXIT]]
131+
; CHECK: loop.7:
132+
; CHECK-NEXT: call void @bar()
133+
; CHECK-NEXT: br label [[LATCH_7:%.*]]
134+
; CHECK: latch.7:
135+
; CHECK-NEXT: call void @bar()
136+
; CHECK-NEXT: [[CMP2_7:%.*]] = icmp ule i64 7, [[N]]
137+
; CHECK-NEXT: br i1 [[CMP2_7]], label [[LOOP_8:%.*]], label [[EXIT]]
138+
; CHECK: loop.8:
139+
; CHECK-NEXT: call void @bar()
140+
; CHECK-NEXT: br label [[LATCH_8:%.*]]
141+
; CHECK: latch.8:
142+
; CHECK-NEXT: call void @bar()
143+
; CHECK-NEXT: [[CMP2_8:%.*]] = icmp ule i64 8, [[N]]
144+
; CHECK-NEXT: br i1 [[CMP2_8]], label [[LOOP_9:%.*]], label [[EXIT]]
145+
; CHECK: loop.9:
146+
; CHECK-NEXT: call void @bar()
147+
; CHECK-NEXT: br label [[LATCH_9:%.*]]
148+
; CHECK: latch.9:
149+
; CHECK-NEXT: call void @bar()
150+
; CHECK-NEXT: [[CMP2_9:%.*]] = icmp ule i64 9, [[N]]
151+
; CHECK-NEXT: br i1 [[CMP2_9]], label [[LOOP_10:%.*]], label [[EXIT]]
152+
; CHECK: loop.10:
153+
; CHECK-NEXT: call void @bar()
154+
; CHECK-NEXT: br label [[LATCH_10:%.*]]
155+
; CHECK: latch.10:
156+
; CHECK-NEXT: call void @bar()
157+
; CHECK-NEXT: [[CMP2_10:%.*]] = icmp ule i64 10, [[N]]
158+
; CHECK-NEXT: br i1 [[CMP2_10]], label [[LOOP_11:%.*]], label [[EXIT]]
159+
; CHECK: loop.11:
160+
; CHECK-NEXT: call void @bar()
161+
; CHECK-NEXT: br i1 false, label [[LATCH_11:%.*]], label [[EXIT]]
162+
; CHECK: latch.11:
163+
; CHECK-NEXT: call void @bar()
164+
; CHECK-NEXT: br label [[EXIT]]
93165
;
94166
entry:
95167
br label %loop

llvm/test/Transforms/LoopUnroll/partial-unroll-non-latch-exit.ll

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,60 @@ define i1 @test(i64* %a1, i64* %a2) {
1010
; CHECK-NEXT: start:
1111
; CHECK-NEXT: br label [[LOOP:%.*]]
1212
; CHECK: loop:
13-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[START:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
14-
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV]], 24
15-
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LATCH]]
13+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[START:%.*]] ], [ [[IV_NEXT_4:%.*]], [[LATCH_4:%.*]] ]
14+
; CHECK-NEXT: br label [[LATCH:%.*]]
1615
; CHECK: latch:
17-
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
16+
; CHECK-NEXT: [[IV_NEXT:%.*]] = add nuw nsw i64 [[IV]], 1
1817
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, i64* [[A1:%.*]], i64 [[IV]]
1918
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, i64* [[A2:%.*]], i64 [[IV]]
2019
; CHECK-NEXT: [[LOAD1:%.*]] = load i64, i64* [[GEP1]], align 8
2120
; CHECK-NEXT: [[LOAD2:%.*]] = load i64, i64* [[GEP2]], align 8
2221
; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]]
23-
; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
22+
; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP_1:%.*]], label [[EXIT:%.*]]
2423
; CHECK: exit:
25-
; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ true, [[LOOP]] ]
24+
; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ false, [[LATCH_1:%.*]] ], [ false, [[LATCH_2:%.*]] ], [ false, [[LATCH_3:%.*]] ], [ true, [[LOOP_4:%.*]] ], [ false, [[LATCH_4]] ]
2625
; CHECK-NEXT: ret i1 [[EXIT_VAL]]
26+
; CHECK: loop.1:
27+
; CHECK-NEXT: br label [[LATCH_1]]
28+
; CHECK: latch.1:
29+
; CHECK-NEXT: [[IV_NEXT_1:%.*]] = add nuw nsw i64 [[IV_NEXT]], 1
30+
; CHECK-NEXT: [[GEP1_1:%.*]] = getelementptr inbounds i64, i64* [[A1]], i64 [[IV_NEXT]]
31+
; CHECK-NEXT: [[GEP2_1:%.*]] = getelementptr inbounds i64, i64* [[A2]], i64 [[IV_NEXT]]
32+
; CHECK-NEXT: [[LOAD1_1:%.*]] = load i64, i64* [[GEP1_1]], align 8
33+
; CHECK-NEXT: [[LOAD2_1:%.*]] = load i64, i64* [[GEP2_1]], align 8
34+
; CHECK-NEXT: [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]]
35+
; CHECK-NEXT: br i1 [[EXITCOND2_1]], label [[LOOP_2:%.*]], label [[EXIT]]
36+
; CHECK: loop.2:
37+
; CHECK-NEXT: br label [[LATCH_2]]
38+
; CHECK: latch.2:
39+
; CHECK-NEXT: [[IV_NEXT_2:%.*]] = add nuw nsw i64 [[IV_NEXT_1]], 1
40+
; CHECK-NEXT: [[GEP1_2:%.*]] = getelementptr inbounds i64, i64* [[A1]], i64 [[IV_NEXT_1]]
41+
; CHECK-NEXT: [[GEP2_2:%.*]] = getelementptr inbounds i64, i64* [[A2]], i64 [[IV_NEXT_1]]
42+
; CHECK-NEXT: [[LOAD1_2:%.*]] = load i64, i64* [[GEP1_2]], align 8
43+
; CHECK-NEXT: [[LOAD2_2:%.*]] = load i64, i64* [[GEP2_2]], align 8
44+
; CHECK-NEXT: [[EXITCOND2_2:%.*]] = icmp eq i64 [[LOAD1_2]], [[LOAD2_2]]
45+
; CHECK-NEXT: br i1 [[EXITCOND2_2]], label [[LOOP_3:%.*]], label [[EXIT]]
46+
; CHECK: loop.3:
47+
; CHECK-NEXT: br label [[LATCH_3]]
48+
; CHECK: latch.3:
49+
; CHECK-NEXT: [[IV_NEXT_3:%.*]] = add nuw nsw i64 [[IV_NEXT_2]], 1
50+
; CHECK-NEXT: [[GEP1_3:%.*]] = getelementptr inbounds i64, i64* [[A1]], i64 [[IV_NEXT_2]]
51+
; CHECK-NEXT: [[GEP2_3:%.*]] = getelementptr inbounds i64, i64* [[A2]], i64 [[IV_NEXT_2]]
52+
; CHECK-NEXT: [[LOAD1_3:%.*]] = load i64, i64* [[GEP1_3]], align 8
53+
; CHECK-NEXT: [[LOAD2_3:%.*]] = load i64, i64* [[GEP2_3]], align 8
54+
; CHECK-NEXT: [[EXITCOND2_3:%.*]] = icmp eq i64 [[LOAD1_3]], [[LOAD2_3]]
55+
; CHECK-NEXT: br i1 [[EXITCOND2_3]], label [[LOOP_4]], label [[EXIT]]
56+
; CHECK: loop.4:
57+
; CHECK-NEXT: [[EXITCOND_4:%.*]] = icmp eq i64 [[IV_NEXT_3]], 24
58+
; CHECK-NEXT: br i1 [[EXITCOND_4]], label [[EXIT]], label [[LATCH_4]]
59+
; CHECK: latch.4:
60+
; CHECK-NEXT: [[IV_NEXT_4]] = add nuw nsw i64 [[IV_NEXT_3]], 1
61+
; CHECK-NEXT: [[GEP1_4:%.*]] = getelementptr inbounds i64, i64* [[A1]], i64 [[IV_NEXT_3]]
62+
; CHECK-NEXT: [[GEP2_4:%.*]] = getelementptr inbounds i64, i64* [[A2]], i64 [[IV_NEXT_3]]
63+
; CHECK-NEXT: [[LOAD1_4:%.*]] = load i64, i64* [[GEP1_4]], align 8
64+
; CHECK-NEXT: [[LOAD2_4:%.*]] = load i64, i64* [[GEP2_4]], align 8
65+
; CHECK-NEXT: [[EXITCOND2_4:%.*]] = icmp eq i64 [[LOAD1_4]], [[LOAD2_4]]
66+
; CHECK-NEXT: br i1 [[EXITCOND2_4]], label [[LOOP]], label [[EXIT]]
2767
;
2868
start:
2969
br label %loop

llvm/test/Transforms/LoopUnroll/runtime-loop-known-exit.ll

Lines changed: 5 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,80 +10,19 @@ define void @test(i32 %s, i32 %n) {
1010
; CHECK-LABEL: @test(
1111
; CHECK-NEXT: entry:
1212
; CHECK-NEXT: [[N2:%.*]] = add i32 [[S:%.*]], 123
13-
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
14-
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[S]]
15-
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[N]], [[S]]
16-
; CHECK-NEXT: [[XTRAITER:%.*]] = and i32 [[TMP1]], 7
17-
; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i32 [[XTRAITER]], 0
18-
; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[LOOP_PROL_PREHEADER:%.*]], label [[LOOP_PROL_LOOPEXIT:%.*]]
19-
; CHECK: loop.prol.preheader:
20-
; CHECK-NEXT: br label [[LOOP_PROL:%.*]]
21-
; CHECK: loop.prol:
22-
; CHECK-NEXT: [[I_PROL:%.*]] = phi i32 [ [[S]], [[LOOP_PROL_PREHEADER]] ], [ [[I_INC_PROL:%.*]], [[LATCH_PROL:%.*]] ]
23-
; CHECK-NEXT: [[PROL_ITER:%.*]] = phi i32 [ [[XTRAITER]], [[LOOP_PROL_PREHEADER]] ], [ [[PROL_ITER_SUB:%.*]], [[LATCH_PROL]] ]
24-
; CHECK-NEXT: [[C1_PROL:%.*]] = icmp eq i32 [[I_PROL]], [[N2]]
25-
; CHECK-NEXT: br i1 [[C1_PROL]], label [[EXIT1_LOOPEXIT1:%.*]], label [[LATCH_PROL]]
26-
; CHECK: latch.prol:
27-
; CHECK-NEXT: [[C2_PROL:%.*]] = icmp eq i32 [[I_PROL]], [[N]]
28-
; CHECK-NEXT: [[I_INC_PROL]] = add i32 [[I_PROL]], 1
29-
; CHECK-NEXT: [[PROL_ITER_SUB]] = sub i32 [[PROL_ITER]], 1
30-
; CHECK-NEXT: [[PROL_ITER_CMP:%.*]] = icmp ne i32 [[PROL_ITER_SUB]], 0
31-
; CHECK-NEXT: br i1 [[PROL_ITER_CMP]], label [[LOOP_PROL]], label [[LOOP_PROL_LOOPEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
32-
; CHECK: loop.prol.loopexit.unr-lcssa:
33-
; CHECK-NEXT: [[I_UNR_PH:%.*]] = phi i32 [ [[I_INC_PROL]], [[LATCH_PROL]] ]
34-
; CHECK-NEXT: br label [[LOOP_PROL_LOOPEXIT]]
35-
; CHECK: loop.prol.loopexit:
36-
; CHECK-NEXT: [[I_UNR:%.*]] = phi i32 [ [[S]], [[ENTRY:%.*]] ], [ [[I_UNR_PH]], [[LOOP_PROL_LOOPEXIT_UNR_LCSSA]] ]
37-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 7
38-
; CHECK-NEXT: br i1 [[TMP3]], label [[EXIT2:%.*]], label [[ENTRY_NEW:%.*]]
39-
; CHECK: entry.new:
4013
; CHECK-NEXT: br label [[LOOP:%.*]]
4114
; CHECK: loop:
42-
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_UNR]], [[ENTRY_NEW]] ], [ [[I_INC_7:%.*]], [[LATCH_7:%.*]] ]
15+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[S]], [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LATCH:%.*]] ]
4316
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[I]], [[N2]]
44-
; CHECK-NEXT: br i1 [[C1]], label [[EXIT1_LOOPEXIT:%.*]], label [[LATCH:%.*]]
17+
; CHECK-NEXT: br i1 [[C1]], label [[EXIT1:%.*]], label [[LATCH]]
4518
; CHECK: latch:
46-
; CHECK-NEXT: [[I_INC:%.*]] = add i32 [[I]], 1
47-
; CHECK-NEXT: [[C1_1:%.*]] = icmp eq i32 [[I_INC]], [[N2]]
48-
; CHECK-NEXT: br i1 [[C1_1]], label [[EXIT1_LOOPEXIT]], label [[LATCH_1:%.*]]
49-
; CHECK: exit1.loopexit:
50-
; CHECK-NEXT: br label [[EXIT1:%.*]]
51-
; CHECK: exit1.loopexit1:
52-
; CHECK-NEXT: br label [[EXIT1]]
19+
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[I]], [[N:%.*]]
20+
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
21+
; CHECK-NEXT: br i1 [[C2]], label [[EXIT2:%.*]], label [[LOOP]]
5322
; CHECK: exit1:
5423
; CHECK-NEXT: ret void
55-
; CHECK: exit2.unr-lcssa:
56-
; CHECK-NEXT: br label [[EXIT2]]
5724
; CHECK: exit2:
5825
; CHECK-NEXT: ret void
59-
; CHECK: latch.1:
60-
; CHECK-NEXT: [[I_INC_1:%.*]] = add i32 [[I_INC]], 1
61-
; CHECK-NEXT: [[C1_2:%.*]] = icmp eq i32 [[I_INC_1]], [[N2]]
62-
; CHECK-NEXT: br i1 [[C1_2]], label [[EXIT1_LOOPEXIT]], label [[LATCH_2:%.*]]
63-
; CHECK: latch.2:
64-
; CHECK-NEXT: [[I_INC_2:%.*]] = add i32 [[I_INC_1]], 1
65-
; CHECK-NEXT: [[C1_3:%.*]] = icmp eq i32 [[I_INC_2]], [[N2]]
66-
; CHECK-NEXT: br i1 [[C1_3]], label [[EXIT1_LOOPEXIT]], label [[LATCH_3:%.*]]
67-
; CHECK: latch.3:
68-
; CHECK-NEXT: [[I_INC_3:%.*]] = add i32 [[I_INC_2]], 1
69-
; CHECK-NEXT: [[C1_4:%.*]] = icmp eq i32 [[I_INC_3]], [[N2]]
70-
; CHECK-NEXT: br i1 [[C1_4]], label [[EXIT1_LOOPEXIT]], label [[LATCH_4:%.*]]
71-
; CHECK: latch.4:
72-
; CHECK-NEXT: [[I_INC_4:%.*]] = add i32 [[I_INC_3]], 1
73-
; CHECK-NEXT: [[C1_5:%.*]] = icmp eq i32 [[I_INC_4]], [[N2]]
74-
; CHECK-NEXT: br i1 [[C1_5]], label [[EXIT1_LOOPEXIT]], label [[LATCH_5:%.*]]
75-
; CHECK: latch.5:
76-
; CHECK-NEXT: [[I_INC_5:%.*]] = add i32 [[I_INC_4]], 1
77-
; CHECK-NEXT: [[C1_6:%.*]] = icmp eq i32 [[I_INC_5]], [[N2]]
78-
; CHECK-NEXT: br i1 [[C1_6]], label [[EXIT1_LOOPEXIT]], label [[LATCH_6:%.*]]
79-
; CHECK: latch.6:
80-
; CHECK-NEXT: [[I_INC_6:%.*]] = add i32 [[I_INC_5]], 1
81-
; CHECK-NEXT: [[C1_7:%.*]] = icmp eq i32 [[I_INC_6]], [[N2]]
82-
; CHECK-NEXT: br i1 [[C1_7]], label [[EXIT1_LOOPEXIT]], label [[LATCH_7]]
83-
; CHECK: latch.7:
84-
; CHECK-NEXT: [[C2_7:%.*]] = icmp eq i32 [[I_INC_6]], [[N]]
85-
; CHECK-NEXT: [[I_INC_7]] = add i32 [[I_INC_6]], 1
86-
; CHECK-NEXT: br i1 [[C2_7]], label [[EXIT2_UNR_LCSSA:%.*]], label [[LOOP]]
8726
;
8827
entry:
8928
%n2 = add i32 %s, 123

0 commit comments

Comments
 (0)