xref: /llvm-project/llvm/test/Transforms/LoopUnroll/multiple-exits.ll (revision 5103ef64fe4f60cc0fd518b514c712f4b4c03d98)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=loop-unroll -S < %s | FileCheck %s
3
4declare void @bar()
5
6define void @test1() {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    call void @bar()
12; CHECK-NEXT:    br label [[LATCH:%.*]]
13; CHECK:       latch:
14; CHECK-NEXT:    call void @bar()
15; CHECK-NEXT:    call void @bar()
16; CHECK-NEXT:    br label [[LATCH_1:%.*]]
17; CHECK:       latch.1:
18; CHECK-NEXT:    call void @bar()
19; CHECK-NEXT:    call void @bar()
20; CHECK-NEXT:    br label [[LATCH_2:%.*]]
21; CHECK:       latch.2:
22; CHECK-NEXT:    call void @bar()
23; CHECK-NEXT:    call void @bar()
24; CHECK-NEXT:    br label [[LATCH_3:%.*]]
25; CHECK:       latch.3:
26; CHECK-NEXT:    call void @bar()
27; CHECK-NEXT:    call void @bar()
28; CHECK-NEXT:    br label [[LATCH_4:%.*]]
29; CHECK:       latch.4:
30; CHECK-NEXT:    call void @bar()
31; CHECK-NEXT:    call void @bar()
32; CHECK-NEXT:    br label [[LATCH_5:%.*]]
33; CHECK:       latch.5:
34; CHECK-NEXT:    call void @bar()
35; CHECK-NEXT:    call void @bar()
36; CHECK-NEXT:    br label [[LATCH_6:%.*]]
37; CHECK:       latch.6:
38; CHECK-NEXT:    call void @bar()
39; CHECK-NEXT:    call void @bar()
40; CHECK-NEXT:    br label [[LATCH_7:%.*]]
41; CHECK:       latch.7:
42; CHECK-NEXT:    call void @bar()
43; CHECK-NEXT:    call void @bar()
44; CHECK-NEXT:    br label [[LATCH_8:%.*]]
45; CHECK:       latch.8:
46; CHECK-NEXT:    call void @bar()
47; CHECK-NEXT:    call void @bar()
48; CHECK-NEXT:    br label [[LATCH_9:%.*]]
49; CHECK:       latch.9:
50; CHECK-NEXT:    call void @bar()
51; CHECK-NEXT:    call void @bar()
52; CHECK-NEXT:    br i1 false, label [[LATCH_10:%.*]], label [[EXIT:%.*]]
53; CHECK:       latch.10:
54; CHECK-NEXT:    call void @bar()
55; CHECK-NEXT:    br label [[EXIT]]
56; CHECK:       exit:
57; CHECK-NEXT:    ret void
58;
59entry:
60  br label %loop
61loop:
62  %iv = phi i64 [0, %entry], [%iv.next, %latch]
63  %iv.next = add i64 %iv, 1
64  call void @bar()
65  %cmp1 = icmp ult i64 %iv, 10
66  br i1 %cmp1, label %latch, label %exit
67latch:
68  call void @bar()
69  %cmp2 = icmp ult i64 %iv, 20
70  br i1 %cmp2, label %loop, label %exit
71exit:
72  ret void
73}
74
75; Fully unroll this loop by 10, but leave the unrolled latch
76; tests since we don't know if %N < 10, and break the backedge.
77define void @test2(i64 %N) {
78; CHECK-LABEL: @test2(
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    br label [[LOOP:%.*]]
81; CHECK:       loop:
82; CHECK-NEXT:    call void @bar()
83; CHECK-NEXT:    br label [[LATCH:%.*]]
84; CHECK:       latch:
85; CHECK-NEXT:    call void @bar()
86; CHECK-NEXT:    br i1 true, label [[LOOP_1:%.*]], label [[EXIT:%.*]]
87; CHECK:       loop.1:
88; CHECK-NEXT:    call void @bar()
89; CHECK-NEXT:    br label [[LATCH_1:%.*]]
90; CHECK:       latch.1:
91; CHECK-NEXT:    call void @bar()
92; CHECK-NEXT:    [[CMP2_1:%.*]] = icmp ule i64 1, [[N:%.*]]
93; CHECK-NEXT:    br i1 [[CMP2_1]], label [[LOOP_2:%.*]], label [[EXIT]]
94; CHECK:       loop.2:
95; CHECK-NEXT:    call void @bar()
96; CHECK-NEXT:    br label [[LATCH_2:%.*]]
97; CHECK:       latch.2:
98; CHECK-NEXT:    call void @bar()
99; CHECK-NEXT:    [[CMP2_2:%.*]] = icmp ule i64 2, [[N]]
100; CHECK-NEXT:    br i1 [[CMP2_2]], label [[LOOP_3:%.*]], label [[EXIT]]
101; CHECK:       loop.3:
102; CHECK-NEXT:    call void @bar()
103; CHECK-NEXT:    br label [[LATCH_3:%.*]]
104; CHECK:       latch.3:
105; CHECK-NEXT:    call void @bar()
106; CHECK-NEXT:    [[CMP2_3:%.*]] = icmp ule i64 3, [[N]]
107; CHECK-NEXT:    br i1 [[CMP2_3]], label [[LOOP_4:%.*]], label [[EXIT]]
108; CHECK:       loop.4:
109; CHECK-NEXT:    call void @bar()
110; CHECK-NEXT:    br label [[LATCH_4:%.*]]
111; CHECK:       latch.4:
112; CHECK-NEXT:    call void @bar()
113; CHECK-NEXT:    [[CMP2_4:%.*]] = icmp ule i64 4, [[N]]
114; CHECK-NEXT:    br i1 [[CMP2_4]], label [[LOOP_5:%.*]], label [[EXIT]]
115; CHECK:       loop.5:
116; CHECK-NEXT:    call void @bar()
117; CHECK-NEXT:    br label [[LATCH_5:%.*]]
118; CHECK:       latch.5:
119; CHECK-NEXT:    call void @bar()
120; CHECK-NEXT:    [[CMP2_5:%.*]] = icmp ule i64 5, [[N]]
121; CHECK-NEXT:    br i1 [[CMP2_5]], label [[LOOP_6:%.*]], label [[EXIT]]
122; CHECK:       loop.6:
123; CHECK-NEXT:    call void @bar()
124; CHECK-NEXT:    br label [[LATCH_6:%.*]]
125; CHECK:       latch.6:
126; CHECK-NEXT:    call void @bar()
127; CHECK-NEXT:    [[CMP2_6:%.*]] = icmp ule i64 6, [[N]]
128; CHECK-NEXT:    br i1 [[CMP2_6]], label [[LOOP_7:%.*]], label [[EXIT]]
129; CHECK:       loop.7:
130; CHECK-NEXT:    call void @bar()
131; CHECK-NEXT:    br label [[LATCH_7:%.*]]
132; CHECK:       latch.7:
133; CHECK-NEXT:    call void @bar()
134; CHECK-NEXT:    [[CMP2_7:%.*]] = icmp ule i64 7, [[N]]
135; CHECK-NEXT:    br i1 [[CMP2_7]], label [[LOOP_8:%.*]], label [[EXIT]]
136; CHECK:       loop.8:
137; CHECK-NEXT:    call void @bar()
138; CHECK-NEXT:    br label [[LATCH_8:%.*]]
139; CHECK:       latch.8:
140; CHECK-NEXT:    call void @bar()
141; CHECK-NEXT:    [[CMP2_8:%.*]] = icmp ule i64 8, [[N]]
142; CHECK-NEXT:    br i1 [[CMP2_8]], label [[LOOP_9:%.*]], label [[EXIT]]
143; CHECK:       loop.9:
144; CHECK-NEXT:    call void @bar()
145; CHECK-NEXT:    br label [[LATCH_9:%.*]]
146; CHECK:       latch.9:
147; CHECK-NEXT:    call void @bar()
148; CHECK-NEXT:    [[CMP2_9:%.*]] = icmp ule i64 9, [[N]]
149; CHECK-NEXT:    br i1 [[CMP2_9]], label [[LOOP_10:%.*]], label [[EXIT]]
150; CHECK:       loop.10:
151; CHECK-NEXT:    call void @bar()
152; CHECK-NEXT:    br label [[LATCH_10:%.*]]
153; CHECK:       latch.10:
154; CHECK-NEXT:    call void @bar()
155; CHECK-NEXT:    [[CMP2_10:%.*]] = icmp ule i64 10, [[N]]
156; CHECK-NEXT:    br i1 [[CMP2_10]], label [[LOOP_11:%.*]], label [[EXIT]]
157; CHECK:       loop.11:
158; CHECK-NEXT:    call void @bar()
159; CHECK-NEXT:    br i1 false, label [[LATCH_11:%.*]], label [[EXIT]]
160; CHECK:       latch.11:
161; CHECK-NEXT:    call void @bar()
162; CHECK-NEXT:    br label [[EXIT]]
163; CHECK:       exit:
164; CHECK-NEXT:    ret void
165;
166entry:
167  br label %loop
168loop:
169  %iv = phi i64 [0, %entry], [%iv.next, %latch]
170  %iv.next = add i64 %iv, 1
171  call void @bar()
172  %cmp1 = icmp ule i64 %iv, 10
173  br i1 %cmp1, label %latch, label %exit
174latch:
175  call void @bar()
176  %cmp2 = icmp ule i64 %iv, %N
177  br i1 %cmp2, label %loop, label %exit
178exit:
179  ret void
180}
181
182
183; TODO: We could partially unroll this by 2.
184define void @test3(i64 %N, i64 %M) {
185; CHECK-LABEL: @test3(
186; CHECK-NEXT:  entry:
187; CHECK-NEXT:    [[N_MASKED:%.*]] = and i64 [[N:%.*]], 65520
188; CHECK-NEXT:    [[M_MASKED:%.*]] = and i64 [[M:%.*]], 65520
189; CHECK-NEXT:    br label [[LOOP:%.*]]
190; CHECK:       loop:
191; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
192; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
193; CHECK-NEXT:    call void @bar()
194; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i64 [[IV]], [[N_MASKED]]
195; CHECK-NEXT:    br i1 [[CMP1]], label [[LATCH]], label [[EXIT:%.*]]
196; CHECK:       latch:
197; CHECK-NEXT:    call void @bar()
198; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i64 [[IV]], [[M_MASKED]]
199; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP]], label [[EXIT]]
200; CHECK:       exit:
201; CHECK-NEXT:    ret void
202;
203entry:
204  %N.masked = and i64 %N, 65520 ; 0xfff0
205  %M.masked = and i64 %M, 65520 ; 0xfff0
206  br label %loop
207loop:
208  %iv = phi i64 [0, %entry], [%iv.next, %latch]
209  %iv.next = add i64 %iv, 1
210  call void @bar()
211  %cmp1 = icmp ule i64 %iv, %N.masked
212  br i1 %cmp1, label %latch, label %exit
213latch:
214  call void @bar()
215  %cmp2 = icmp ule i64 %iv, %M.masked
216  br i1 %cmp2, label %loop, label %exit
217exit:
218  ret void
219}
220