xref: /llvm-project/llvm/test/Transforms/LoopUnroll/convergent.controlled.ll (revision e0ac087ff004f7a63ba64b9685f4f098d6ee54c5)
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
3
4declare void @f() convergent
5declare void @g()
6
7; Although this loop contains a convergent instruction, it should be
8; fully unrolled.
9define 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
26;
27entry:
28  %anchor = call token @llvm.experimental.convergence.anchor()
29  br label %l3
30
31l3:
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
37
38a:
39  call void @f() [ "convergencectrl"(token %tok.loop) ]
40  br i1 %exitcond, label %exit, label %l3
41
42exit:
43  ret i32 0
44}
45
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.
49define 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
75;
76entry:
77  %anchor = call token @llvm.experimental.convergence.anchor()
78  %loop_ctl = mul nsw i32 %n, 12
79  br label %l3
80
81l3:
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
85
86a:
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
91
92exit:
93  ret i32 0
94}
95
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.
99define 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
137;
138entry:
139  %anchor = call token @llvm.experimental.convergence.anchor()
140  %loop_ctl = mul nsw i32 %n, 24
141  br label %l3, !llvm.loop !0
142
143l3:
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
147
148a:
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
153
154exit:
155  ret i32 0
156}
157
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.
160define 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
175;
176entry:
177  %anchor = call token @llvm.experimental.convergence.anchor()
178  br label %l3, !llvm.loop !1
179
180l3:
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
187
188exit:
189  ret void
190}
191
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.
194define 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
210;
211entry:
212  %anchor = call token @llvm.experimental.convergence.anchor()
213  %loop_ctl = mul nsw i32 %n, 2
214  br label %l3, !llvm.loop !1
215
216l3:
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
223
224exit:
225  ret i32 0
226}
227
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.
231define 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
245;
246entry:
247  %anchor = call token @llvm.experimental.convergence.anchor()
248  br label %l3, !llvm.loop !1
249
250l3:
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
257
258exit:
259  ret i32 0
260}
261
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.
266define 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
279;
280entry:
281  %anchor = call token @llvm.experimental.convergence.anchor()
282  br label %l3, !llvm.loop !1
283
284l3:
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
291
292exit:
293  ret i32 0
294}
295
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.
298define 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
333;
334entry:
335  br label %l3, !llvm.loop !1
336
337l3:
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
344
345exit:
346  ret i32 0
347}
348
349; Don't unroll a loop that is extended by convergence controls.
350;
351; We could theoretically duplicate the extension part, but this is not
352; implemented.
353define 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
366;
367entry:
368  br label %l3, !llvm.loop !1
369
370l3:
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
376
377exit:
378  call void @f() [ "convergencectrl"(token %tok.loop) ]
379  ret i32 0
380}
381
382; Inner loop is extended beyond the outer loop. No unrolling possible.
383
384define 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
403;
404entry:
405  br label %l3
406
407l3:
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
413
414l2:
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
418
419latch:
420  br i1 %exitcond, label %exit, label %l3
421
422exit:
423  call void @f() [ "convergencectrl"(token %tok.l2) ]
424  ret i32 0
425}
426
427; Inner loop is extended inside the outer loop. Outer loop is unrolled.
428
429define 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
463;
464entry:
465  br label %l3
466
467l3:
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
473
474l2:
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
478
479latch:
480  call void @f() [ "convergencectrl"(token %tok.l2) ]
481  br i1 %exitcond, label %exit, label %l3
482
483exit:
484  ret i32 0
485}
486
487; No extension. Both loops unrolled.
488
489define 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
535;
536entry:
537  br label %l3
538
539l3:
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
545
546l2:
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
550
551latch:
552  br i1 %exitcond, label %exit, label %l3
553
554exit:
555  ret i32 0
556}
557
558declare token @llvm.experimental.convergence.anchor()
559declare token @llvm.experimental.convergence.loop()
560
561!0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}}
562!1 = !{!1, !{!"llvm.loop.unroll.count", i32 2}}
563