1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s
4 declare void @f() convergent
7 ; Although this loop contains a convergent instruction, it should be
9 define i32 @full_unroll() {
10 ; CHECK-LABEL: @full_unroll(
12 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
13 ; CHECK-NEXT: br label [[L3:%.*]]
15 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
16 ; CHECK-NEXT: br label [[A:%.*]]
18 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
19 ; CHECK-NEXT: br label [[A_1:%.*]]
21 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
22 ; CHECK-NEXT: br label [[A_2:%.*]]
24 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
25 ; CHECK-NEXT: ret i32 0
28 %anchor = call token @llvm.experimental.convergence.anchor()
32 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ]
33 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
34 %inc = add nsw i32 %x.0, 1
35 %exitcond = icmp eq i32 %inc, 3
39 call void @f() [ "convergencectrl"(token %tok.loop) ]
40 br i1 %exitcond, label %exit, label %l3
46 ; This loop contains a convergent instruction, but it should be partially
47 ; unrolled. The unroll count is the largest power of 2 that divides the
48 ; multiple -- 4, in this case.
49 define i32 @runtime_unroll(i32 %n) {
50 ; CHECK-LABEL: @runtime_unroll(
52 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
53 ; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 12
54 ; CHECK-NEXT: br label [[L3:%.*]]
56 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_3:%.*]], [[A_3:%.*]] ]
57 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
58 ; CHECK-NEXT: br label [[A:%.*]]
60 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
61 ; CHECK-NEXT: br label [[A_1:%.*]]
63 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
64 ; CHECK-NEXT: br label [[A_2:%.*]]
66 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
67 ; CHECK-NEXT: br label [[A_3]]
69 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
70 ; CHECK-NEXT: [[INC_3]] = add nsw i32 [[X_0]], 4
71 ; CHECK-NEXT: [[EXITCOND_3:%.*]] = icmp eq i32 [[INC_3]], [[LOOP_CTL]]
72 ; CHECK-NEXT: br i1 [[EXITCOND_3]], label [[EXIT:%.*]], label [[L3]]
74 ; CHECK-NEXT: ret i32 0
77 %anchor = call token @llvm.experimental.convergence.anchor()
78 %loop_ctl = mul nsw i32 %n, 12
82 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ]
83 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
87 call void @f() [ "convergencectrl"(token %tok.loop) ]
88 %inc = add nsw i32 %x.0, 1
89 %exitcond = icmp eq i32 %inc, %loop_ctl
90 br i1 %exitcond, label %exit, label %l3
96 ; This loop contains a convergent instruction, so its partial unroll
97 ; count must divide its trip multiple. This overrides its unroll
98 ; pragma -- we unroll exactly 8 times, even though 16 is requested.
99 define i32 @pragma_unroll(i32 %n) {
100 ; CHECK-LABEL: @pragma_unroll(
102 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
103 ; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 24
104 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
106 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_7:%.*]], [[A_7:%.*]] ]
107 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
108 ; CHECK-NEXT: br label [[A:%.*]]
110 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
111 ; CHECK-NEXT: br label [[A_1:%.*]]
113 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
114 ; CHECK-NEXT: br label [[A_2:%.*]]
116 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
117 ; CHECK-NEXT: br label [[A_3:%.*]]
119 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
120 ; CHECK-NEXT: br label [[A_4:%.*]]
122 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
123 ; CHECK-NEXT: br label [[A_5:%.*]]
125 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
126 ; CHECK-NEXT: br label [[A_6:%.*]]
128 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
129 ; CHECK-NEXT: br label [[A_7]]
131 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
132 ; CHECK-NEXT: [[INC_7]] = add nsw i32 [[X_0]], 8
133 ; CHECK-NEXT: [[EXITCOND_7:%.*]] = icmp eq i32 [[INC_7]], [[LOOP_CTL]]
134 ; CHECK-NEXT: br i1 [[EXITCOND_7]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP2:![0-9]+]]
136 ; CHECK-NEXT: ret i32 0
139 %anchor = call token @llvm.experimental.convergence.anchor()
140 %loop_ctl = mul nsw i32 %n, 24
141 br label %l3, !llvm.loop !0
144 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ]
145 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
149 call void @f() [ "convergencectrl"(token %tok.loop) ]
150 %inc = add nsw i32 %x.0, 1
151 %exitcond = icmp eq i32 %inc, %loop_ctl
152 br i1 %exitcond, label %exit, label %l3, !llvm.loop !0
158 ; This loop contains a convergent instruction. Since the pragma loop unroll
159 ; count 2 divides trip count 4. The loop unroll should respect the pragma.
160 define void @pragma_unroll_divisible_trip_count() {
161 ; CHECK-LABEL: @pragma_unroll_divisible_trip_count(
163 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
164 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4:![0-9]+]]
166 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_1:%.*]], [[L3]] ]
167 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
168 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
169 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
170 ; CHECK-NEXT: [[INC_1]] = add nuw nsw i32 [[X_0]], 2
171 ; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[INC_1]], 4
172 ; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP6:![0-9]+]]
174 ; CHECK-NEXT: ret void
177 %anchor = call token @llvm.experimental.convergence.anchor()
178 br label %l3, !llvm.loop !1
181 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
182 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
183 call void @f() [ "convergencectrl"(token %tok.loop) ]
184 %inc = add nsw i32 %x.0, 1
185 %exitcond = icmp eq i32 %inc, 4
186 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
192 ; This loop contains a convergent instruction. Since the pragma loop unroll
193 ; count 2 divides trip multiple 2. The loop unroll should respect the pragma.
194 define i32 @pragma_unroll_divisible_trip_multiple(i32 %n) {
195 ; CHECK-LABEL: @pragma_unroll_divisible_trip_multiple(
197 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
198 ; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 2
199 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]]
201 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_1:%.*]], [[L3]] ]
202 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
203 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
204 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
205 ; CHECK-NEXT: [[INC_1]] = add nsw i32 [[X_0]], 2
206 ; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[INC_1]], [[LOOP_CTL]]
207 ; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP7:![0-9]+]]
209 ; CHECK-NEXT: ret i32 0
212 %anchor = call token @llvm.experimental.convergence.anchor()
213 %loop_ctl = mul nsw i32 %n, 2
214 br label %l3, !llvm.loop !1
217 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
218 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
219 call void @f() [ "convergencectrl"(token %tok.loop) ]
220 %inc = add nsw i32 %x.0, 1
221 %exitcond = icmp eq i32 %inc, %loop_ctl
222 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
228 ; This loop contains a convergent instruction. Since the pragma loop unroll
229 ; count 2 is unknown to divide runtime trip count, the loop is not unrolled
230 ; since remainder is forbidden for unrolling convergent loop.
231 define i32 @pragma_unroll_indivisible_runtime_trip_count(i32 %n) {
232 ; CHECK-LABEL: @pragma_unroll_indivisible_runtime_trip_count(
234 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
235 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]]
237 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[L3]] ]
238 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
239 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
240 ; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1
241 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N:%.*]]
242 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP4]]
244 ; CHECK-NEXT: ret i32 0
247 %anchor = call token @llvm.experimental.convergence.anchor()
248 br label %l3, !llvm.loop !1
251 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
252 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
253 call void @f() [ "convergencectrl"(token %tok.loop) ]
254 %inc = add nsw i32 %x.0, 1
255 %exitcond = icmp eq i32 %inc, %n
256 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
262 ; This loop contains a convergent instruction. Since the pragma loop unroll
263 ; count 2 does not divide trip count 5, the loop is not unrolled by 2
264 ; since remainder is forbidden for unrolling convergent loop. Instead, the
265 ; loop gets fully unrolled.
266 define i32 @pragma_unroll_indivisible_trip_count() {
267 ; CHECK-LABEL: @pragma_unroll_indivisible_trip_count(
269 ; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
270 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]]
272 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
273 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
274 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
275 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
276 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
277 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
278 ; CHECK-NEXT: ret i32 0
281 %anchor = call token @llvm.experimental.convergence.anchor()
282 br label %l3, !llvm.loop !1
285 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
286 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
287 call void @f() [ "convergencectrl"(token %tok.loop) ]
288 %inc = add nsw i32 %x.0, 1
289 %exitcond = icmp eq i32 %inc, 5
290 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
296 ; This loop contains a convergent instruction that is anchored inside the loop
297 ; itself. It is unrolled by 2 with remainder, as requested by the loop metadata.
298 define i32 @pragma_unroll_with_remainder(i32 %n) {
299 ; CHECK-LABEL: @pragma_unroll_with_remainder(
301 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[N:%.*]]
302 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -1
303 ; CHECK-NEXT: [[XTRAITER:%.*]] = and i32 [[TMP0]], 1
304 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 1
305 ; CHECK-NEXT: br i1 [[TMP2]], label [[EXIT_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]]
307 ; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i32 [[TMP0]], [[XTRAITER]]
308 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]]
310 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[INC_1:%.*]], [[L3]] ]
311 ; CHECK-NEXT: [[NITER:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_1:%.*]], [[L3]] ]
312 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor()
313 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
314 ; CHECK-NEXT: [[TOK_LOOP_1:%.*]] = call token @llvm.experimental.convergence.anchor()
315 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP_1]]) ]
316 ; CHECK-NEXT: [[INC_1]] = add nsw i32 [[X_0]], 2
317 ; CHECK-NEXT: [[NITER_NEXT_1]] = add i32 [[NITER]], 2
318 ; CHECK-NEXT: [[NITER_NCMP_1:%.*]] = icmp eq i32 [[NITER_NEXT_1]], [[UNROLL_ITER]]
319 ; CHECK-NEXT: br i1 [[NITER_NCMP_1]], label [[EXIT_UNR_LCSSA_LOOPEXIT:%.*]], label [[L3]], !llvm.loop [[LOOP8:![0-9]+]]
320 ; CHECK: exit.unr-lcssa.loopexit:
321 ; CHECK-NEXT: br label [[EXIT_UNR_LCSSA]]
322 ; CHECK: exit.unr-lcssa:
323 ; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i32 [[XTRAITER]], 0
324 ; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[L3_EPIL_PREHEADER:%.*]], label [[EXIT:%.*]]
325 ; CHECK: l3.epil.preheader:
326 ; CHECK-NEXT: br label [[L3_EPIL:%.*]]
328 ; CHECK-NEXT: [[TOK_LOOP_EPIL:%.*]] = call token @llvm.experimental.convergence.anchor()
329 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP_EPIL]]) ]
330 ; CHECK-NEXT: br label [[EXIT]]
332 ; CHECK-NEXT: ret i32 0
335 br label %l3, !llvm.loop !1
338 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
339 %tok.loop = call token @llvm.experimental.convergence.anchor()
340 call void @f() [ "convergencectrl"(token %tok.loop) ]
341 %inc = add nsw i32 %x.0, 1
342 %exitcond = icmp eq i32 %inc, %n
343 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
349 ; Don't unroll a loop that is extended by convergence controls.
351 ; We could theoretically duplicate the extension part, but this is not
353 define i32 @extended_loop(i32 %n) {
354 ; CHECK-LABEL: @extended_loop(
356 ; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]]
358 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[L3]] ]
359 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor()
360 ; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1
361 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N:%.*]]
362 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP4]]
364 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
365 ; CHECK-NEXT: ret i32 0
368 br label %l3, !llvm.loop !1
371 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
372 %tok.loop = call token @llvm.experimental.convergence.anchor()
373 %inc = add nsw i32 %x.0, 1
374 %exitcond = icmp eq i32 %inc, %n
375 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
378 call void @f() [ "convergencectrl"(token %tok.loop) ]
382 ; Inner loop is extended beyond the outer loop. No unrolling possible.
384 define i32 @extended_inner_loop_1(i32 %n, i1 %cond) {
385 ; CHECK-LABEL: @extended_inner_loop_1(
387 ; CHECK-NEXT: br label [[L3:%.*]]
389 ; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LATCH:%.*]] ]
390 ; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor()
391 ; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1
392 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 4
393 ; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]]
395 ; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor()
396 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
397 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2]], label [[LATCH]], !llvm.loop [[LOOP4]]
399 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]]
401 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
402 ; CHECK-NEXT: ret i32 0
408 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ]
409 %tok.loop = call token @llvm.experimental.convergence.anchor()
410 %inc = add nsw i32 %x.0, 1
411 %exitcond = icmp eq i32 %inc, 4
412 br label %l2, !llvm.loop !1
415 %tok.l2 = call token @llvm.experimental.convergence.anchor()
416 call void @f() [ "convergencectrl"(token %tok.l2) ]
417 br i1 %cond, label %l2, label %latch, !llvm.loop !1
420 br i1 %exitcond, label %exit, label %l3
423 call void @f() [ "convergencectrl"(token %tok.l2) ]
427 ; Inner loop is extended inside the outer loop. Outer loop is unrolled.
429 define i32 @extended_inner_loop_2(i32 %n, i1 %cond) {
430 ; CHECK-LABEL: @extended_inner_loop_2(
432 ; CHECK-NEXT: br label [[L3:%.*]]
434 ; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]]
436 ; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor()
437 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
438 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2]], label [[LATCH:%.*]], !llvm.loop [[LOOP4]]
440 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
441 ; CHECK-NEXT: br label [[L2_1:%.*]], !llvm.loop [[LOOP4]]
443 ; CHECK-NEXT: [[TOK_L2_1:%.*]] = call token @llvm.experimental.convergence.anchor()
444 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ]
445 ; CHECK-NEXT: br i1 [[COND]], label [[L2_1]], label [[LATCH_1:%.*]], !llvm.loop [[LOOP4]]
447 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ]
448 ; CHECK-NEXT: br label [[L2_2:%.*]], !llvm.loop [[LOOP4]]
450 ; CHECK-NEXT: [[TOK_L2_2:%.*]] = call token @llvm.experimental.convergence.anchor()
451 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ]
452 ; CHECK-NEXT: br i1 [[COND]], label [[L2_2]], label [[LATCH_2:%.*]], !llvm.loop [[LOOP4]]
454 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ]
455 ; CHECK-NEXT: br label [[L2_3:%.*]], !llvm.loop [[LOOP4]]
457 ; CHECK-NEXT: [[TOK_L2_3:%.*]] = call token @llvm.experimental.convergence.anchor()
458 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ]
459 ; CHECK-NEXT: br i1 [[COND]], label [[L2_3]], label [[LATCH_3:%.*]], !llvm.loop [[LOOP4]]
461 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ]
462 ; CHECK-NEXT: ret i32 0
468 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ]
469 %tok.loop = call token @llvm.experimental.convergence.anchor()
470 %inc = add nsw i32 %x.0, 1
471 %exitcond = icmp eq i32 %inc, 4
472 br label %l2, !llvm.loop !1
475 %tok.l2 = call token @llvm.experimental.convergence.anchor()
476 call void @f() [ "convergencectrl"(token %tok.l2) ]
477 br i1 %cond, label %l2, label %latch, !llvm.loop !1
480 call void @f() [ "convergencectrl"(token %tok.l2) ]
481 br i1 %exitcond, label %exit, label %l3
487 ; No extension. Both loops unrolled.
489 define i32 @unroll_nest(i32 %n, i1 %cond) {
490 ; CHECK-LABEL: @unroll_nest(
492 ; CHECK-NEXT: br label [[L3:%.*]]
494 ; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]]
496 ; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor()
497 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
498 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2_1:%.*]], label [[LATCH:%.*]], !llvm.loop [[LOOP4]]
500 ; CHECK-NEXT: [[TOK_L2_1:%.*]] = call token @llvm.experimental.convergence.anchor()
501 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ]
502 ; CHECK-NEXT: br i1 [[COND]], label [[L2]], label [[LATCH]], !llvm.loop [[LOOP9:![0-9]+]]
504 ; CHECK-NEXT: br label [[L2_12:%.*]], !llvm.loop [[LOOP4]]
506 ; CHECK-NEXT: [[TOK_L2_11:%.*]] = call token @llvm.experimental.convergence.anchor()
507 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_11]]) ]
508 ; CHECK-NEXT: br i1 [[COND]], label [[L2_1_1:%.*]], label [[LATCH_1:%.*]], !llvm.loop [[LOOP4]]
510 ; CHECK-NEXT: [[TOK_L2_1_1:%.*]] = call token @llvm.experimental.convergence.anchor()
511 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_1]]) ]
512 ; CHECK-NEXT: br i1 [[COND]], label [[L2_12]], label [[LATCH_1]], !llvm.loop [[LOOP9]]
514 ; CHECK-NEXT: br label [[L2_2:%.*]], !llvm.loop [[LOOP4]]
516 ; CHECK-NEXT: [[TOK_L2_2:%.*]] = call token @llvm.experimental.convergence.anchor()
517 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ]
518 ; CHECK-NEXT: br i1 [[COND]], label [[L2_1_2:%.*]], label [[LATCH_2:%.*]], !llvm.loop [[LOOP4]]
520 ; CHECK-NEXT: [[TOK_L2_1_2:%.*]] = call token @llvm.experimental.convergence.anchor()
521 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_2]]) ]
522 ; CHECK-NEXT: br i1 [[COND]], label [[L2_2]], label [[LATCH_2]], !llvm.loop [[LOOP9]]
524 ; CHECK-NEXT: br label [[L2_3:%.*]], !llvm.loop [[LOOP4]]
526 ; CHECK-NEXT: [[TOK_L2_3:%.*]] = call token @llvm.experimental.convergence.anchor()
527 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ]
528 ; CHECK-NEXT: br i1 [[COND]], label [[L2_1_3:%.*]], label [[LATCH_3:%.*]], !llvm.loop [[LOOP4]]
530 ; CHECK-NEXT: [[TOK_L2_1_3:%.*]] = call token @llvm.experimental.convergence.anchor()
531 ; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_3]]) ]
532 ; CHECK-NEXT: br i1 [[COND]], label [[L2_3]], label [[LATCH_3]], !llvm.loop [[LOOP9]]
534 ; CHECK-NEXT: ret i32 0
540 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ]
541 %tok.loop = call token @llvm.experimental.convergence.anchor()
542 %inc = add nsw i32 %x.0, 1
543 %exitcond = icmp eq i32 %inc, 4
544 br label %l2, !llvm.loop !1
547 %tok.l2 = call token @llvm.experimental.convergence.anchor()
548 call void @f() [ "convergencectrl"(token %tok.l2) ]
549 br i1 %cond, label %l2, label %latch, !llvm.loop !1
552 br i1 %exitcond, label %exit, label %l3
558 declare token @llvm.experimental.convergence.anchor()
559 declare token @llvm.experimental.convergence.loop()
561 !0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}}
562 !1 = !{!1, !{!"llvm.loop.unroll.count", i32 2}}