150
|
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
2 ; RUN: opt < %s -indvars -S | FileCheck %s
|
|
3 ; This is a collection of tests specifically for LFTR of multiple exit loops.
|
|
4 ; The actual LFTR performed is trivial so as to focus on the loop structure
|
|
5 ; aspects.
|
|
6
|
|
7 ; Provide legal integer types.
|
|
8 target datalayout = "n8:16:32:64"
|
|
9
|
|
10 @A = external global i32
|
|
11
|
|
12 define void @analyzeable_early_exit(i32 %n) {
|
|
13 ; CHECK-LABEL: @analyzeable_early_exit(
|
|
14 ; CHECK-NEXT: entry:
|
|
15 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
16 ; CHECK: loop:
|
|
17 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
18 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
19 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
20 ; CHECK: latch:
|
|
21 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
22 ; CHECK-NEXT: store i32 [[IV]], i32* @A
|
|
23 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
|
|
24 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
|
|
25 ; CHECK: exit:
|
|
26 ; CHECK-NEXT: ret void
|
|
27 ;
|
|
28 entry:
|
|
29 br label %loop
|
|
30
|
|
31 loop:
|
|
32 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
33 %earlycnd = icmp ult i32 %iv, %n
|
|
34 br i1 %earlycnd, label %latch, label %exit
|
|
35
|
|
36 latch:
|
|
37 %iv.next = add i32 %iv, 1
|
|
38 store i32 %iv, i32* @A
|
|
39 %c = icmp ult i32 %iv.next, 1000
|
|
40 br i1 %c, label %loop, label %exit
|
|
41
|
|
42 exit:
|
|
43 ret void
|
|
44 }
|
|
45
|
|
46 define void @unanalyzeable_early_exit() {
|
|
47 ; CHECK-LABEL: @unanalyzeable_early_exit(
|
|
48 ; CHECK-NEXT: entry:
|
|
49 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
50 ; CHECK: loop:
|
|
51 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
52 ; CHECK-NEXT: [[VOL:%.*]] = load volatile i32, i32* @A
|
|
53 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
|
|
54 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
55 ; CHECK: latch:
|
|
56 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
57 ; CHECK-NEXT: store i32 [[IV]], i32* @A
|
|
58 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
|
|
59 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
|
|
60 ; CHECK: exit:
|
|
61 ; CHECK-NEXT: ret void
|
|
62 ;
|
|
63 entry:
|
|
64 br label %loop
|
|
65
|
|
66 loop:
|
|
67 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
68 %vol = load volatile i32, i32* @A
|
|
69 %earlycnd = icmp ne i32 %vol, 0
|
|
70 br i1 %earlycnd, label %latch, label %exit
|
|
71
|
|
72 latch:
|
|
73 %iv.next = add i32 %iv, 1
|
|
74 store i32 %iv, i32* @A
|
|
75 %c = icmp ult i32 %iv.next, 1000
|
|
76 br i1 %c, label %loop, label %exit
|
|
77
|
|
78 exit:
|
|
79 ret void
|
|
80 }
|
|
81
|
|
82
|
|
83 define void @multiple_early_exits(i32 %n, i32 %m) {
|
|
84 ; CHECK-LABEL: @multiple_early_exits(
|
|
85 ; CHECK-NEXT: entry:
|
|
86 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
87 ; CHECK: loop:
|
|
88 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
89 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
90 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
|
|
91 ; CHECK: continue:
|
|
92 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
93 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
|
|
94 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
|
|
95 ; CHECK: latch:
|
|
96 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
97 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
98 ; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
|
|
99 ; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
|
|
100 ; CHECK: exit:
|
|
101 ; CHECK-NEXT: ret void
|
|
102 ;
|
|
103 entry:
|
|
104 br label %loop
|
|
105
|
|
106 loop:
|
|
107 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
108 %earlycnd = icmp ult i32 %iv, %n
|
|
109 br i1 %earlycnd, label %continue, label %exit
|
|
110
|
|
111 continue:
|
|
112 store volatile i32 %iv, i32* @A
|
|
113 %earlycnd2 = icmp ult i32 %iv, %m
|
|
114 br i1 %earlycnd2, label %latch, label %exit
|
|
115
|
|
116 latch:
|
|
117 %iv.next = add i32 %iv, 1
|
|
118 store volatile i32 %iv, i32* @A
|
|
119 %c = icmp ult i32 %iv.next, 1000
|
|
120 br i1 %c, label %loop, label %exit
|
|
121
|
|
122 exit:
|
|
123 ret void
|
|
124 }
|
|
125
|
|
126 ; Note: This slightly odd form is what indvars itself produces for multiple
|
|
127 ; exits without a side effect between them.
|
|
128 define void @compound_early_exit(i32 %n, i32 %m) {
|
|
129 ; CHECK-LABEL: @compound_early_exit(
|
|
130 ; CHECK-NEXT: entry:
|
173
|
131 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[M:%.*]], [[N:%.*]]
|
|
132 ; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[M]], i32 [[N]]
|
150
|
133 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
134 ; CHECK: loop:
|
|
135 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
173
|
136 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[UMIN]]
|
|
137 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
150
|
138 ; CHECK: latch:
|
|
139 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
140 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
173
|
141 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
|
|
142 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
|
150
|
143 ; CHECK: exit:
|
|
144 ; CHECK-NEXT: ret void
|
|
145 ;
|
|
146 entry:
|
|
147 br label %loop
|
|
148
|
|
149 loop:
|
|
150 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
151 %earlycnd = icmp ult i32 %iv, %n
|
|
152 %earlycnd2 = icmp ult i32 %iv, %m
|
|
153 %and = and i1 %earlycnd, %earlycnd2
|
|
154 br i1 %and, label %latch, label %exit
|
|
155
|
|
156 latch:
|
|
157 %iv.next = add i32 %iv, 1
|
|
158 store volatile i32 %iv, i32* @A
|
|
159 %c = icmp ult i32 %iv.next, 1000
|
|
160 br i1 %c, label %loop, label %exit
|
|
161
|
|
162 exit:
|
|
163 ret void
|
|
164 }
|
|
165
|
|
166
|
|
167 define void @unanalyzeable_latch(i32 %n) {
|
|
168 ; CHECK-LABEL: @unanalyzeable_latch(
|
|
169 ; CHECK-NEXT: entry:
|
|
170 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
171 ; CHECK: loop:
|
|
172 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
173 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
174 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
175 ; CHECK: latch:
|
|
176 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
177 ; CHECK-NEXT: store i32 [[IV]], i32* @A
|
|
178 ; CHECK-NEXT: [[VOL:%.*]] = load volatile i32, i32* @A
|
|
179 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[VOL]], 1000
|
|
180 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
|
|
181 ; CHECK: exit:
|
|
182 ; CHECK-NEXT: ret void
|
|
183 ;
|
|
184 entry:
|
|
185 br label %loop
|
|
186
|
|
187 loop:
|
|
188 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
189 %earlycnd = icmp ult i32 %iv, %n
|
|
190 br i1 %earlycnd, label %latch, label %exit
|
|
191
|
|
192 latch:
|
|
193 %iv.next = add i32 %iv, 1
|
|
194 store i32 %iv, i32* @A
|
|
195 %vol = load volatile i32, i32* @A
|
|
196 %c = icmp ult i32 %vol, 1000
|
|
197 br i1 %c, label %loop, label %exit
|
|
198
|
|
199 exit:
|
|
200 ret void
|
|
201 }
|
|
202
|
|
203 define void @single_exit_no_latch(i32 %n) {
|
|
204 ; CHECK-LABEL: @single_exit_no_latch(
|
|
205 ; CHECK-NEXT: entry:
|
|
206 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
207 ; CHECK: loop:
|
|
208 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
209 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
210 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
211 ; CHECK: latch:
|
|
212 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
213 ; CHECK-NEXT: store i32 [[IV]], i32* @A
|
|
214 ; CHECK-NEXT: br label [[LOOP]]
|
|
215 ; CHECK: exit:
|
|
216 ; CHECK-NEXT: ret void
|
|
217 ;
|
|
218 entry:
|
|
219 br label %loop
|
|
220
|
|
221 loop:
|
|
222 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
223 %earlycnd = icmp ult i32 %iv, %n
|
|
224 br i1 %earlycnd, label %latch, label %exit
|
|
225
|
|
226 latch:
|
|
227 %iv.next = add i32 %iv, 1
|
|
228 store i32 %iv, i32* @A
|
|
229 br label %loop
|
|
230
|
|
231 exit:
|
|
232 ret void
|
|
233 }
|
|
234
|
|
235 ; Multiple exits which could be LFTRed, but the latch itself is not an
|
|
236 ; exiting block.
|
|
237 define void @no_latch_exit(i32 %n, i32 %m) {
|
|
238 ; CHECK-LABEL: @no_latch_exit(
|
|
239 ; CHECK-NEXT: entry:
|
|
240 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
241 ; CHECK: loop:
|
|
242 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
243 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
244 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
|
|
245 ; CHECK: continue:
|
|
246 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
247 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
|
|
248 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
|
|
249 ; CHECK: latch:
|
|
250 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
251 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
252 ; CHECK-NEXT: br label [[LOOP]]
|
|
253 ; CHECK: exit:
|
|
254 ; CHECK-NEXT: ret void
|
|
255 ;
|
|
256 entry:
|
|
257 br label %loop
|
|
258
|
|
259 loop:
|
|
260 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
261 %earlycnd = icmp ult i32 %iv, %n
|
|
262 br i1 %earlycnd, label %continue, label %exit
|
|
263
|
|
264 continue:
|
|
265 store volatile i32 %iv, i32* @A
|
|
266 %earlycnd2 = icmp ult i32 %iv, %m
|
|
267 br i1 %earlycnd2, label %latch, label %exit
|
|
268
|
|
269 latch:
|
|
270 store volatile i32 %iv, i32* @A
|
|
271 %iv.next = add i32 %iv, 1
|
|
272 br label %loop
|
|
273
|
|
274 exit:
|
|
275 ret void
|
|
276 }
|
|
277
|
|
278 ;; Show the value of multiple exit LFTR (being able to eliminate all but
|
|
279 ;; one IV when exit tests involve multiple IVs).
|
|
280 define void @combine_ivs(i32 %n) {
|
|
281 ; CHECK-LABEL: @combine_ivs(
|
|
282 ; CHECK-NEXT: entry:
|
|
283 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
284 ; CHECK: loop:
|
|
285 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
286 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
287 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
288 ; CHECK: latch:
|
|
289 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
290 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
291 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
|
|
292 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
|
|
293 ; CHECK: exit:
|
|
294 ; CHECK-NEXT: ret void
|
|
295 ;
|
|
296 entry:
|
|
297 br label %loop
|
|
298
|
|
299 loop:
|
|
300 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
301 %iv2 = phi i32 [ 1, %entry], [ %iv2.next, %latch]
|
|
302 %earlycnd = icmp ult i32 %iv, %n
|
|
303 br i1 %earlycnd, label %latch, label %exit
|
|
304
|
|
305 latch:
|
|
306 %iv.next = add i32 %iv, 1
|
|
307 %iv2.next = add i32 %iv2, 1
|
|
308 store volatile i32 %iv, i32* @A
|
|
309 %c = icmp ult i32 %iv2.next, 1000
|
|
310 br i1 %c, label %loop, label %exit
|
|
311
|
|
312 exit:
|
|
313 ret void
|
|
314 }
|
|
315
|
|
316 ; We can remove the decrementing IV entirely
|
|
317 define void @combine_ivs2(i32 %n) {
|
|
318 ; CHECK-LABEL: @combine_ivs2(
|
|
319 ; CHECK-NEXT: entry:
|
|
320 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
321 ; CHECK: loop:
|
|
322 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
323 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
324 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
325 ; CHECK: latch:
|
|
326 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
327 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
328 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
|
|
329 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
|
|
330 ; CHECK: exit:
|
|
331 ; CHECK-NEXT: ret void
|
|
332 ;
|
|
333 entry:
|
|
334 br label %loop
|
|
335
|
|
336 loop:
|
|
337 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
338 %iv2 = phi i32 [ 1000, %entry], [ %iv2.next, %latch]
|
|
339 %earlycnd = icmp ult i32 %iv, %n
|
|
340 br i1 %earlycnd, label %latch, label %exit
|
|
341
|
|
342 latch:
|
|
343 %iv.next = add i32 %iv, 1
|
|
344 %iv2.next = sub i32 %iv2, 1
|
|
345 store volatile i32 %iv, i32* @A
|
|
346 %c = icmp ugt i32 %iv2.next, 0
|
|
347 br i1 %c, label %loop, label %exit
|
|
348
|
|
349 exit:
|
|
350 ret void
|
|
351 }
|
|
352
|
|
353 ; An example where we can eliminate an f(i) computation entirely
|
|
354 ; from a multiple exit loop with LFTR.
|
|
355 define void @simplify_exit_test(i32 %n) {
|
|
356 ; CHECK-LABEL: @simplify_exit_test(
|
|
357 ; CHECK-NEXT: entry:
|
|
358 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
359 ; CHECK: loop:
|
|
360 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
361 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
|
|
362 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
363 ; CHECK: latch:
|
|
364 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
365 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
366 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
|
|
367 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
|
|
368 ; CHECK: exit:
|
|
369 ; CHECK-NEXT: ret void
|
|
370 ;
|
|
371 entry:
|
|
372 br label %loop
|
|
373
|
|
374 loop:
|
|
375 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
376 %earlycnd = icmp ult i32 %iv, %n
|
|
377 br i1 %earlycnd, label %latch, label %exit
|
|
378
|
|
379 latch:
|
|
380 %iv.next = add i32 %iv, 1
|
|
381 %fx = shl i32 %iv, 4
|
|
382 store volatile i32 %iv, i32* @A
|
|
383 %c = icmp ult i32 %fx, 1024
|
|
384 br i1 %c, label %loop, label %exit
|
|
385
|
|
386 exit:
|
|
387 ret void
|
|
388 }
|
|
389
|
|
390
|
|
391 ; Another example where we can remove an f(i) type computation, but this
|
|
392 ; time in a loop w/o a statically computable exit count.
|
|
393 define void @simplify_exit_test2(i32 %n) {
|
|
394 ; CHECK-LABEL: @simplify_exit_test2(
|
|
395 ; CHECK-NEXT: entry:
|
|
396 ; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
397 ; CHECK: loop:
|
|
398 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
|
|
399 ; CHECK-NEXT: [[VOL:%.*]] = load volatile i32, i32* @A
|
|
400 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
|
|
401 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
|
|
402 ; CHECK: latch:
|
|
403 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
404 ; CHECK-NEXT: [[FX:%.*]] = udiv i32 [[IV]], 4
|
|
405 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
|
|
406 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[FX]], 1024
|
|
407 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
|
|
408 ; CHECK: exit:
|
|
409 ; CHECK-NEXT: ret void
|
|
410 ;
|
|
411 entry:
|
|
412 br label %loop
|
|
413
|
|
414 loop:
|
|
415 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
|
|
416 %vol = load volatile i32, i32* @A
|
|
417 %earlycnd = icmp ne i32 %vol, 0
|
|
418 br i1 %earlycnd, label %latch, label %exit
|
|
419
|
|
420 latch:
|
|
421 %iv.next = add i32 %iv, 1
|
|
422 %fx = udiv i32 %iv, 4
|
|
423 store volatile i32 %iv, i32* @A
|
|
424 %c = icmp ult i32 %fx, 1024
|
|
425 br i1 %c, label %loop, label %exit
|
|
426
|
|
427 exit:
|
|
428 ret void
|
|
429 }
|
|
430
|
|
431 ; Demonstrate a case where two nested loops share a single exiting block.
|
|
432 ; The key point is that the exit count is *different* for the two loops, and
|
|
433 ; thus we can't rewrite the exit for the outer one. There are three sub-cases
|
|
434 ; which can happen here: a) the outer loop has a backedge taken count of zero
|
|
435 ; (for the case where we know the inner exit is known taken), b) the exit is
|
|
436 ; known never taken (but may have an exit count outside the range of the IV)
|
|
437 ; or c) the outer loop has an unanalyzable exit count (where we can't tell).
|
|
438 define void @nested(i32 %n) {
|
|
439 ; CHECK-LABEL: @nested(
|
|
440 ; CHECK-NEXT: entry:
|
|
441 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
|
|
442 ; CHECK-NEXT: br label [[OUTER:%.*]]
|
|
443 ; CHECK: outer:
|
|
444 ; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV1_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
|
|
445 ; CHECK-NEXT: store volatile i32 [[IV1]], i32* @A
|
|
446 ; CHECK-NEXT: [[IV1_NEXT]] = add nuw nsw i32 [[IV1]], 1
|
|
447 ; CHECK-NEXT: br label [[INNER:%.*]]
|
|
448 ; CHECK: inner:
|
|
449 ; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 0, [[OUTER]] ], [ [[IV2_NEXT:%.*]], [[INNER_LATCH:%.*]] ]
|
|
450 ; CHECK-NEXT: store volatile i32 [[IV2]], i32* @A
|
|
451 ; CHECK-NEXT: [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
|
|
452 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], 20
|
|
453 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNER_LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
454 ; CHECK: inner_latch:
|
|
455 ; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp ne i32 [[IV2_NEXT]], [[TMP0]]
|
|
456 ; CHECK-NEXT: br i1 [[EXITCOND2]], label [[INNER]], label [[OUTER_LATCH]]
|
|
457 ; CHECK: outer_latch:
|
|
458 ; CHECK-NEXT: [[EXITCOND3:%.*]] = icmp ne i32 [[IV1_NEXT]], 21
|
|
459 ; CHECK-NEXT: br i1 [[EXITCOND3]], label [[OUTER]], label [[EXIT_LOOPEXIT1:%.*]]
|
|
460 ; CHECK: exit.loopexit:
|
|
461 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
462 ; CHECK: exit.loopexit1:
|
|
463 ; CHECK-NEXT: br label [[EXIT]]
|
|
464 ; CHECK: exit:
|
|
465 ; CHECK-NEXT: ret void
|
|
466 ;
|
|
467 entry:
|
|
468 br label %outer
|
|
469
|
|
470 outer:
|
|
471 %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer_latch ]
|
|
472 store volatile i32 %iv1, i32* @A
|
|
473 %iv1.next = add i32 %iv1, 1
|
|
474 br label %inner
|
|
475
|
|
476 inner:
|
|
477 %iv2 = phi i32 [ 0, %outer ], [ %iv2.next, %inner_latch ]
|
|
478 store volatile i32 %iv2, i32* @A
|
|
479 %iv2.next = add i32 %iv2, 1
|
|
480 %innertest = icmp ult i32 %iv2, 20
|
|
481 br i1 %innertest, label %inner_latch, label %exit
|
|
482
|
|
483 inner_latch:
|
|
484 %innertestb = icmp ult i32 %iv2, %n
|
|
485 br i1 %innertestb, label %inner, label %outer_latch
|
|
486
|
|
487 outer_latch:
|
|
488 %outertest = icmp ult i32 %iv1, 20
|
|
489 br i1 %outertest, label %outer, label %exit
|
|
490
|
|
491 exit:
|
|
492 ret void
|
|
493 }
|