1; RUN: opt < %s -cycles -analyze -enable-new-pm=0 | FileCheck %s -check-prefix=CHECK
2; RUN: opt < %s -disable-output -passes='print<cycles>' 2>&1 | FileCheck %s -check-prefix=CHECK
3
4define void @empty() {
5; CHECK-LABEL: CycleInfo for function: empty
6; CHECK-NOT:       depth
7
8  ret void
9}
10
11define void @simple() {
12; CHECK-LABEL: CycleInfo for function: simple
13; CHECK:           depth=1: entries(loop)
14entry:
15  br label %loop
16
17loop:
18  br i1 undef, label %loop, label %exit
19
20exit:
21  ret void
22}
23
24define void @two_latches() {
25; CHECK-LABEL: CycleInfo for function: two_latches
26; CHECK:           depth=1: entries(loop) loop_next
27entry:
28  br label %loop
29
30loop:
31  br i1 undef, label %loop, label %loop_next
32
33loop_next:
34  br i1 undef, label %exit, label %loop
35
36exit:
37  ret void
38}
39
40define void @nested_simple() {
41; CHECK-LABEL: CycleInfo for function: nested_simple
42; CHECK:           depth=1: entries(outer_header) outer_latch inner
43; CHECK:               depth=2: entries(inner)
44entry:
45  br label %outer_header
46
47outer_header:
48  br label %inner
49
50inner:
51  br i1 undef, label %inner, label %outer_latch
52
53outer_latch:
54  br i1 undef, label %outer_header, label %exit
55
56exit:
57  ret void
58}
59
60define void @nested_outer_latch_in_inner_loop() {
61; CHECK-LABEL: CycleInfo for function: nested_outer_latch_in_inner_loop
62; CHECK:           depth=1: entries(outer_header) inner_header inner_latch
63; CHECK:               depth=2: entries(inner_header) inner_latch
64entry:
65  br label %outer_header
66
67outer_header:
68  br label %inner_header
69
70inner_header:
71  br i1 undef, label %inner_latch, label %outer_header
72
73inner_latch:
74  br i1 undef, label %exit, label %inner_header
75
76exit:
77  ret void
78}
79
80define void @sibling_loops() {
81; CHECK-LABEL: CycleInfo for function: sibling_loops
82; CHECK-DAG:       depth=1: entries(left)
83; CHECK-DAG:       depth=1: entries(right)
84entry:
85  br i1 undef, label %left, label %right
86
87left:
88  br i1 undef, label %left, label %exit
89
90right:
91  br i1 undef, label %right, label %exit
92
93exit:
94  ret void
95}
96
97define void @serial_loops() {
98; CHECK-LABEL: CycleInfo for function: serial_loops
99; CHECK-DAG:       depth=1: entries(second)
100; CHECK-DAG:       depth=1: entries(first)
101entry:
102  br label %first
103
104first:
105  br i1 undef, label %first, label %second
106
107second:
108  br i1 undef, label %second, label %exit
109
110exit:
111  ret void
112}
113
114define void @nested_sibling_loops() {
115; CHECK-LABEL: CycleInfo for function: nested_sibling_loops
116; CHECK:           depth=1: entries(outer_header) left right
117; CHECK-DAG:           depth=2: entries(right)
118; CHECK-DAG:           depth=2: entries(left)
119entry:
120  br label %outer_header
121
122outer_header:
123  br i1 undef, label %left, label %right
124
125left:
126  switch i32 undef, label %exit [ i32 0, label %left
127                                  i32 1, label %outer_header ]
128
129right:
130  switch i32 undef, label %outer_header [ i32 0, label %exit
131                                          i32 1, label %right ]
132
133exit:
134  ret void
135}
136
137define void @deeper_nest() {
138; CHECK-LABEL: CycleInfo for function: deeper_nest
139; CHECK:           depth=1: entries(outer_header) outer_latch middle_header inner_header inner_latch
140; CHECK:               depth=2: entries(middle_header) inner_header inner_latch
141; CHECK:                   depth=3: entries(inner_header) inner_latch
142entry:
143  br label %outer_header
144
145outer_header:
146  br label %middle_header
147
148middle_header:
149  br label %inner_header
150
151inner_header:
152  br i1 undef, label %middle_header, label %inner_latch
153
154inner_latch:
155  br i1 undef, label %inner_header, label %outer_latch
156
157outer_latch:
158  br i1 undef, label %outer_header, label %exit
159
160exit:
161  ret void
162}
163
164define void @irreducible_basic() {
165; CHECK-LABEL: CycleInfo for function: irreducible_basic
166; CHECK:           depth=1: entries(right left)
167entry:
168  br i1 undef, label %left, label %right
169
170left:
171  br i1 undef, label %right, label %exit
172
173right:
174  br i1 undef, label %left, label %exit
175
176exit:
177  ret void
178}
179
180define void @irreducible_mess() {
181; CHECK-LABEL: CycleInfo for function: irreducible_mess
182; CHECK:           depth=1: entries(B A) D C
183; CHECK:               depth=2: entries(D C A)
184; CHECK:                   depth=3: entries(C A)
185entry:
186  br i1 undef, label %A, label %B
187
188A:
189  br i1 undef, label %C, label %D
190
191B:
192  br i1 undef, label %C, label %D
193
194C:
195  switch i32 undef, label %A [ i32 0, label %D
196                               i32 1, label %exit ]
197
198D:
199  switch i32 undef, label %B [ i32 0, label %C
200                               i32 1, label %exit ]
201
202exit:
203  ret void
204}
205
206define void @irreducible_into_simple_cycle() {
207; CHECK-LABEL: CycleInfo for function: irreducible_into_simple_cycle
208; CHECK:           depth=1: entries(F C A) E D B
209entry:
210  switch i32 undef, label %A [ i32 0, label %C
211                               i32 1, label %F ]
212
213A:
214  br label %B
215
216B:
217  br label %C
218
219C:
220  br label %D
221
222D:
223  br i1 undef, label %E, label %exit
224
225E:
226  br label %F
227
228F:
229  br i1 undef, label %A, label %exit
230
231exit:
232  ret void
233}
234
235define void @irreducible_mountain_bug() {
236; CHECK-LABEL: CycleInfo for function: irreducible_mountain_bug
237; CHECK:           depth=1: entries(while.cond)
238; CHECK:               depth=2: entries(cond.end61 cond.true49) while.body63 while.cond47
239; CHECK:                   depth=3: entries(while.body63 cond.true49) while.cond47
240entry:
241  br i1 undef, label %if.end, label %if.then
242
243if.end:
244  br i1 undef, label %if.then7, label %if.else
245
246if.then7:
247  br label %if.end16
248
249if.else:
250  br label %if.end16
251
252if.end16:
253  br i1 undef, label %while.cond.preheader, label %if.then39
254
255while.cond.preheader:
256  br label %while.cond
257
258while.cond:
259  br i1 undef, label %cond.true49, label %lor.rhs
260
261cond.true49:
262  br i1 undef, label %if.then69, label %while.body63
263
264while.body63:
265  br i1 undef, label %exit, label %while.cond47
266
267while.cond47:
268  br i1 undef, label %cond.true49, label %cond.end61
269
270cond.end61:
271  br i1 undef, label %while.body63, label %while.cond
272
273if.then69:
274  br i1 undef, label %exit, label %while.cond
275
276lor.rhs:
277  br i1 undef, label %cond.end61, label %while.end76
278
279while.end76:
280  br label %exit
281
282if.then39:
283  br i1 undef, label %exit, label %if.end.i145
284
285if.end.i145:
286  br i1 undef, label %exit, label %if.end8.i149
287
288if.end8.i149:
289  br label %exit
290
291if.then:
292  br i1 undef, label %exit, label %if.end.i
293
294if.end.i:
295  br i1 undef, label %exit, label %if.end8.i
296
297if.end8.i:
298  br label %exit
299
300exit:
301  ret void
302}
303