Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopUnroll / convergent.controlled.ll
blob7fd4eb18f16eb88e407b20bde2b23420ecd8caa3
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
5 declare void @g()
7 ; Although this loop contains a convergent instruction, it should be
8 ; fully unrolled.
9 define i32 @full_unroll() {
10 ; CHECK-LABEL: @full_unroll(
11 ; CHECK-NEXT:  entry:
12 ; CHECK-NEXT:    [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
13 ; CHECK-NEXT:    br label [[L3:%.*]]
14 ; CHECK:       l3:
15 ; CHECK-NEXT:    [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ]
16 ; CHECK-NEXT:    br label [[A:%.*]]
17 ; CHECK:       a:
18 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
19 ; CHECK-NEXT:    br label [[A_1:%.*]]
20 ; CHECK:       a.1:
21 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
22 ; CHECK-NEXT:    br label [[A_2:%.*]]
23 ; CHECK:       a.2:
24 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
25 ; CHECK-NEXT:    ret i32 0
27 entry:
28   %anchor = call token @llvm.experimental.convergence.anchor()
29   br label %l3
31 l3:
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
36   br label %a
39   call void @f() [ "convergencectrl"(token %tok.loop) ]
40   br i1 %exitcond, label %exit, label %l3
42 exit:
43   ret i32 0
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(
51 ; CHECK-NEXT:  entry:
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:%.*]]
55 ; CHECK:       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:%.*]]
59 ; CHECK:       a:
60 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
61 ; CHECK-NEXT:    br label [[A_1:%.*]]
62 ; CHECK:       a.1:
63 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
64 ; CHECK-NEXT:    br label [[A_2:%.*]]
65 ; CHECK:       a.2:
66 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
67 ; CHECK-NEXT:    br label [[A_3]]
68 ; CHECK:       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]]
73 ; CHECK:       exit:
74 ; CHECK-NEXT:    ret i32 0
76 entry:
77   %anchor = call token @llvm.experimental.convergence.anchor()
78   %loop_ctl = mul nsw i32 %n, 12
79   br label %l3
81 l3:
82   %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ]
83   %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ]
84   br label %a
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
92 exit:
93   ret i32 0
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(
101 ; CHECK-NEXT:  entry:
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]+]]
105 ; CHECK:       l3:
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:%.*]]
109 ; CHECK:       a:
110 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
111 ; CHECK-NEXT:    br label [[A_1:%.*]]
112 ; CHECK:       a.1:
113 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
114 ; CHECK-NEXT:    br label [[A_2:%.*]]
115 ; CHECK:       a.2:
116 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
117 ; CHECK-NEXT:    br label [[A_3:%.*]]
118 ; CHECK:       a.3:
119 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
120 ; CHECK-NEXT:    br label [[A_4:%.*]]
121 ; CHECK:       a.4:
122 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
123 ; CHECK-NEXT:    br label [[A_5:%.*]]
124 ; CHECK:       a.5:
125 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
126 ; CHECK-NEXT:    br label [[A_6:%.*]]
127 ; CHECK:       a.6:
128 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
129 ; CHECK-NEXT:    br label [[A_7]]
130 ; CHECK:       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]+]]
135 ; CHECK:       exit:
136 ; CHECK-NEXT:    ret i32 0
138 entry:
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) ]
146   br label %a
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
154 exit:
155   ret i32 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(
162 ; CHECK-NEXT:  entry:
163 ; CHECK-NEXT:    [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
164 ; CHECK-NEXT:    br label [[L3:%.*]], !llvm.loop [[LOOP4:![0-9]+]]
165 ; CHECK:       l3:
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]+]]
173 ; CHECK:       exit:
174 ; CHECK-NEXT:    ret void
176 entry:
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
188 exit:
189   ret void
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(
196 ; CHECK-NEXT:  entry:
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]]
200 ; CHECK:       l3:
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]+]]
208 ; CHECK:       exit:
209 ; CHECK-NEXT:    ret i32 0
211 entry:
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
224 exit:
225   ret i32 0
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(
233 ; CHECK-NEXT:  entry:
234 ; CHECK-NEXT:    [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
235 ; CHECK-NEXT:    br label [[L3:%.*]], !llvm.loop [[LOOP4]]
236 ; CHECK:       l3:
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]]
243 ; CHECK:       exit:
244 ; CHECK-NEXT:    ret i32 0
246 entry:
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
258 exit:
259   ret i32 0
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(
268 ; CHECK-NEXT:  entry:
269 ; CHECK-NEXT:    [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor()
270 ; CHECK-NEXT:    br label [[L3:%.*]], !llvm.loop [[LOOP4]]
271 ; CHECK:       l3:
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
280 entry:
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
292 exit:
293   ret i32 0
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(
300 ; CHECK-NEXT:  entry:
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:%.*]]
306 ; CHECK:       entry.new:
307 ; CHECK-NEXT:    [[UNROLL_ITER:%.*]] = sub i32 [[TMP0]], [[XTRAITER]]
308 ; CHECK-NEXT:    br label [[L3:%.*]], !llvm.loop [[LOOP4]]
309 ; CHECK:       l3:
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:%.*]]
327 ; CHECK:       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]]
331 ; CHECK:       exit:
332 ; CHECK-NEXT:    ret i32 0
334 entry:
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
345 exit:
346   ret i32 0
349 ; Don't unroll a loop that is extended by convergence controls.
351 ; We could theoretically duplicate the extension part, but this is not
352 ; implemented.
353 define i32 @extended_loop(i32 %n) {
354 ; CHECK-LABEL: @extended_loop(
355 ; CHECK-NEXT:  entry:
356 ; CHECK-NEXT:    br label [[L3:%.*]], !llvm.loop [[LOOP4]]
357 ; CHECK:       l3:
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]]
363 ; CHECK:       exit:
364 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ]
365 ; CHECK-NEXT:    ret i32 0
367 entry:
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
377 exit:
378   call void @f() [ "convergencectrl"(token %tok.loop) ]
379   ret i32 0
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(
386 ; CHECK-NEXT:  entry:
387 ; CHECK-NEXT:    br label [[L3:%.*]]
388 ; CHECK:       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]]
394 ; CHECK:       l2:
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]]
398 ; CHECK:       latch:
399 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]]
400 ; CHECK:       exit:
401 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
402 ; CHECK-NEXT:    ret i32 0
404 entry:
405   br label %l3
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
419 latch:
420   br i1 %exitcond, label %exit, label %l3
422 exit:
423   call void @f() [ "convergencectrl"(token %tok.l2) ]
424   ret i32 0
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(
431 ; CHECK-NEXT:  entry:
432 ; CHECK-NEXT:    br label [[L3:%.*]]
433 ; CHECK:       l3:
434 ; CHECK-NEXT:    br label [[L2:%.*]], !llvm.loop [[LOOP4]]
435 ; CHECK:       l2:
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]]
439 ; CHECK:       latch:
440 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
441 ; CHECK-NEXT:    br label [[L2_1:%.*]], !llvm.loop [[LOOP4]]
442 ; CHECK:       l2.1:
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]]
446 ; CHECK:       latch.1:
447 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ]
448 ; CHECK-NEXT:    br label [[L2_2:%.*]], !llvm.loop [[LOOP4]]
449 ; CHECK:       l2.2:
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]]
453 ; CHECK:       latch.2:
454 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ]
455 ; CHECK-NEXT:    br label [[L2_3:%.*]], !llvm.loop [[LOOP4]]
456 ; CHECK:       l2.3:
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]]
460 ; CHECK:       latch.3:
461 ; CHECK-NEXT:    call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ]
462 ; CHECK-NEXT:    ret i32 0
464 entry:
465   br label %l3
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
479 latch:
480   call void @f() [ "convergencectrl"(token %tok.l2) ]
481   br i1 %exitcond, label %exit, label %l3
483 exit:
484   ret i32 0
487 ; No extension. Both loops unrolled.
489 define i32 @unroll_nest(i32 %n, i1 %cond) {
490 ; CHECK-LABEL: @unroll_nest(
491 ; CHECK-NEXT:  entry:
492 ; CHECK-NEXT:    br label [[L3:%.*]]
493 ; CHECK:       l3:
494 ; CHECK-NEXT:    br label [[L2:%.*]], !llvm.loop [[LOOP4]]
495 ; CHECK:       l2:
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]]
499 ; CHECK:       l2.1:
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]+]]
503 ; CHECK:       latch:
504 ; CHECK-NEXT:    br label [[L2_12:%.*]], !llvm.loop [[LOOP4]]
505 ; CHECK:       l2.12:
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]]
509 ; CHECK:       l2.1.1:
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]]
513 ; CHECK:       latch.1:
514 ; CHECK-NEXT:    br label [[L2_2:%.*]], !llvm.loop [[LOOP4]]
515 ; CHECK:       l2.2:
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]]
519 ; CHECK:       l2.1.2:
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]]
523 ; CHECK:       latch.2:
524 ; CHECK-NEXT:    br label [[L2_3:%.*]], !llvm.loop [[LOOP4]]
525 ; CHECK:       l2.3:
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]]
529 ; CHECK:       l2.1.3:
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]]
533 ; CHECK:       latch.3:
534 ; CHECK-NEXT:    ret i32 0
536 entry:
537   br label %l3
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
551 latch:
552   br i1 %exitcond, label %exit, label %l3
554 exit:
555   ret i32 0
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}}