[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / test / Transforms / LoopUnroll / full-unroll-keep-first-exit.ll
blobcdc8e944715e51febe2a140e36bc1e3f0bff7ac3
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -loop-unroll < %s | FileCheck %s
3 ; RUN: opt -S -passes='require<opt-remark-emit>,loop(loop-unroll-full)' < %s | FileCheck %s
5 ; Unroll twice, with first loop exit kept
6 define void @s32_max1(i32 %n, i32* %p) {
8 ; CHECK-LABEL: @s32_max1(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 1
11 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
12 ; CHECK:       do.body:
13 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[N]]
14 ; CHECK-NEXT:    store i32 [[N]], i32* [[ARRAYIDX]], align 4
15 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[N]], 1
16 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[N]], [[ADD]]
17 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY_1:%.*]], label [[DO_END:%.*]]
18 ; CHECK:       do.body.1:
19 ; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC]]
20 ; CHECK-NEXT:    store i32 [[INC]], i32* [[ARRAYIDX_1]], align 4
21 ; CHECK-NEXT:    br label [[DO_END]]
22 ; CHECK:       do.end:
23 ; CHECK-NEXT:    ret void
25 entry:
26   %add = add i32 %n, 1
27   br label %do.body
29 do.body:
30   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
31   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
32   store i32 %i.0, i32* %arrayidx, align 4
33   %inc = add i32 %i.0, 1
34   %cmp = icmp slt i32 %i.0, %add
35   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times
37 do.end:
38   ret void
41 ; Unroll thrice, with first loop exit kept
42 define void @s32_max2(i32 %n, i32* %p) {
44 ; CHECK-LABEL: @s32_max2(
45 ; CHECK-NEXT:  entry:
46 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 2
47 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
48 ; CHECK:       do.body:
49 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[N]]
50 ; CHECK-NEXT:    store i32 [[N]], i32* [[ARRAYIDX]], align 4
51 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[N]], 1
52 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[N]], [[ADD]]
53 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY_1:%.*]], label [[DO_END:%.*]]
54 ; CHECK:       do.body.1:
55 ; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC]]
56 ; CHECK-NEXT:    store i32 [[INC]], i32* [[ARRAYIDX_1]], align 4
57 ; CHECK-NEXT:    [[INC_1:%.*]] = add i32 [[INC]], 1
58 ; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC_1]]
59 ; CHECK-NEXT:    store i32 [[INC_1]], i32* [[ARRAYIDX_2]], align 4
60 ; CHECK-NEXT:    br label [[DO_END]]
61 ; CHECK:       do.end:
62 ; CHECK-NEXT:    ret void
64 entry:
65   %add = add i32 %n, 2
66   br label %do.body
68 do.body:
69   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
70   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
71   store i32 %i.0, i32* %arrayidx, align 4
72   %inc = add i32 %i.0, 1
73   %cmp = icmp slt i32 %i.0, %add
74   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times
76 do.end:
77   ret void
80 ; Should not be unrolled
81 define void @s32_maxx(i32 %n, i32 %x, i32* %p) {
83 ; CHECK-LABEL: @s32_maxx(
84 ; CHECK-NEXT:  entry:
85 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], [[N:%.*]]
86 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
87 ; CHECK:       do.body:
88 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[DO_BODY]] ]
89 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[I_0]]
90 ; CHECK-NEXT:    store i32 [[I_0]], i32* [[ARRAYIDX]], align 4
91 ; CHECK-NEXT:    [[INC]] = add i32 [[I_0]], 1
92 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[ADD]]
93 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]
94 ; CHECK:       do.end:
95 ; CHECK-NEXT:    ret void
97 entry:
98   %add = add i32 %x, %n
99   br label %do.body
101 do.body:
102   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
103   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
104   store i32 %i.0, i32* %arrayidx, align 4
105   %inc = add i32 %i.0, 1
106   %cmp = icmp slt i32 %i.0, %add
107   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times
109 do.end:
110   ret void
113 ; Should not be unrolled
114 define void @s32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) {
116 ; CHECK-LABEL: @s32_max2_unpredictable_exit(
117 ; CHECK-NEXT:  entry:
118 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 2
119 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
120 ; CHECK:       do.body:
121 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END:%.*]] ]
122 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I_0]], [[X:%.*]]
123 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_END:%.*]], label [[IF_END]]
124 ; CHECK:       if.end:
125 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[I_0]]
126 ; CHECK-NEXT:    store i32 [[I_0]], i32* [[ARRAYIDX]], align 4
127 ; CHECK-NEXT:    [[INC]] = add i32 [[I_0]], 1
128 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I_0]], [[ADD]]
129 ; CHECK-NEXT:    br i1 [[CMP1]], label [[DO_BODY]], label [[DO_END]]
130 ; CHECK:       do.end:
131 ; CHECK-NEXT:    ret void
133 entry:
134   %add = add i32 %n, 2
135   br label %do.body
137 do.body:
138   %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ]
139   %cmp = icmp eq i32 %i.0, %x
140   br i1 %cmp, label %do.end, label %if.end ; unpredictable
142 if.end:
143   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
144   store i32 %i.0, i32* %arrayidx, align 4
145   %inc = add i32 %i.0, 1
146   %cmp1 = icmp slt i32 %i.0, %add
147   br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times
149 do.end:
150   ret void
153 ; Unroll twice, with first loop exit kept
154 define void @u32_max1(i32 %n, i32* %p) {
156 ; CHECK-LABEL: @u32_max1(
157 ; CHECK-NEXT:  entry:
158 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 1
159 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
160 ; CHECK:       do.body:
161 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[N]]
162 ; CHECK-NEXT:    store i32 [[N]], i32* [[ARRAYIDX]], align 4
163 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[N]], 1
164 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[N]], [[ADD]]
165 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY_1:%.*]], label [[DO_END:%.*]]
166 ; CHECK:       do.body.1:
167 ; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC]]
168 ; CHECK-NEXT:    store i32 [[INC]], i32* [[ARRAYIDX_1]], align 4
169 ; CHECK-NEXT:    br label [[DO_END]]
170 ; CHECK:       do.end:
171 ; CHECK-NEXT:    ret void
173 entry:
174   %add = add i32 %n, 1
175   br label %do.body
177 do.body:
178   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
179   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
180   store i32 %i.0, i32* %arrayidx, align 4
181   %inc = add i32 %i.0, 1
182   %cmp = icmp ult i32 %i.0, %add
183   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times
185 do.end:
186   ret void
189 ; Unroll thrice, with first loop exit kept
190 define void @u32_max2(i32 %n, i32* %p) {
192 ; CHECK-LABEL: @u32_max2(
193 ; CHECK-NEXT:  entry:
194 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 2
195 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
196 ; CHECK:       do.body:
197 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[N]]
198 ; CHECK-NEXT:    store i32 [[N]], i32* [[ARRAYIDX]], align 4
199 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[N]], 1
200 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[N]], [[ADD]]
201 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY_1:%.*]], label [[DO_END:%.*]]
202 ; CHECK:       do.body.1:
203 ; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC]]
204 ; CHECK-NEXT:    store i32 [[INC]], i32* [[ARRAYIDX_1]], align 4
205 ; CHECK-NEXT:    [[INC_1:%.*]] = add i32 [[INC]], 1
206 ; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr i32, i32* [[P]], i32 [[INC_1]]
207 ; CHECK-NEXT:    store i32 [[INC_1]], i32* [[ARRAYIDX_2]], align 4
208 ; CHECK-NEXT:    br label [[DO_END]]
209 ; CHECK:       do.end:
210 ; CHECK-NEXT:    ret void
212 entry:
213   %add = add i32 %n, 2
214   br label %do.body
216 do.body:
217   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
218   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
219   store i32 %i.0, i32* %arrayidx, align 4
220   %inc = add i32 %i.0, 1
221   %cmp = icmp ult i32 %i.0, %add
222   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times
224 do.end:
225   ret void
228 ; Should not be unrolled
229 define void @u32_maxx(i32 %n, i32 %x, i32* %p) {
231 ; CHECK-LABEL: @u32_maxx(
232 ; CHECK-NEXT:  entry:
233 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], [[N:%.*]]
234 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
235 ; CHECK:       do.body:
236 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[DO_BODY]] ]
237 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[I_0]]
238 ; CHECK-NEXT:    store i32 [[I_0]], i32* [[ARRAYIDX]], align 4
239 ; CHECK-NEXT:    [[INC]] = add i32 [[I_0]], 1
240 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[ADD]]
241 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]
242 ; CHECK:       do.end:
243 ; CHECK-NEXT:    ret void
245 entry:
246   %add = add i32 %x, %n
247   br label %do.body
249 do.body:
250   %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
251   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
252   store i32 %i.0, i32* %arrayidx, align 4
253   %inc = add i32 %i.0, 1
254   %cmp = icmp ult i32 %i.0, %add
255   br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times
257 do.end:
258   ret void
261 ; Should not be unrolled
262 define void @u32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) {
264 ; CHECK-LABEL: @u32_max2_unpredictable_exit(
265 ; CHECK-NEXT:  entry:
266 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[N:%.*]], 2
267 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
268 ; CHECK:       do.body:
269 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END:%.*]] ]
270 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I_0]], [[X:%.*]]
271 ; CHECK-NEXT:    br i1 [[CMP]], label [[DO_END:%.*]], label [[IF_END]]
272 ; CHECK:       if.end:
273 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[I_0]]
274 ; CHECK-NEXT:    store i32 [[I_0]], i32* [[ARRAYIDX]], align 4
275 ; CHECK-NEXT:    [[INC]] = add i32 [[I_0]], 1
276 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I_0]], [[ADD]]
277 ; CHECK-NEXT:    br i1 [[CMP1]], label [[DO_BODY]], label [[DO_END]]
278 ; CHECK:       do.end:
279 ; CHECK-NEXT:    ret void
281 entry:
282   %add = add i32 %n, 2
283   br label %do.body
285 do.body:
286   %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ]
287   %cmp = icmp eq i32 %i.0, %x
288   br i1 %cmp, label %do.end, label %if.end ; unpredictable
290 if.end:
291   %arrayidx = getelementptr i32, i32* %p, i32 %i.0
292   store i32 %i.0, i32* %arrayidx, align 4
293   %inc = add i32 %i.0, 1
294   %cmp1 = icmp ult i32 %i.0, %add
295   br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times
297 do.end:
298   ret void