1; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
2
3; This test checks if we update the LoopInfo correctly in the presence
4; of parents, uncles and cousins.
5
6; Function Attrs: alwaysinline
7define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 {
8; CHECK: irce: in function inner_loop: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9
10entry:
11  %len = load i32, i32* %a_len_ptr, !range !0
12  %first.itr.check = icmp sgt i32 %n, 0
13  br i1 %first.itr.check, label %loop, label %exit
14
15loop:                                             ; preds = %in.bounds, %entry
16  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
17  %idx.next = add i32 %idx, 1
18  %abc = icmp slt i32 %idx, %len
19  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
20
21in.bounds:                                        ; preds = %loop
22  %addr = getelementptr i32, i32* %arr, i32 %idx
23  store i32 0, i32* %addr
24  %next = icmp slt i32 %idx.next, %n
25  br i1 %next, label %loop, label %exit
26
27out.of.bounds:                                    ; preds = %loop
28  ret void
29
30exit:                                             ; preds = %in.bounds, %entry
31  ret void
32}
33
34; Function Attrs: alwaysinline
35define void @with_parent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
36; CHECK: irce: in function with_parent: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
37
38entry:
39  br label %loop
40
41loop:                                             ; preds = %inner_loop.exit, %entry
42  %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit ]
43  %idx.next = add i32 %idx, 1
44  %next = icmp ult i32 %idx.next, %parent.count
45  %len.i = load i32, i32* %a_len_ptr, !range !0
46  %first.itr.check.i = icmp sgt i32 %n, 0
47  br i1 %first.itr.check.i, label %loop.i, label %exit.i
48
49loop.i:                                           ; preds = %in.bounds.i, %loop
50  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
51  %idx.next.i = add i32 %idx.i, 1
52  %abc.i = icmp slt i32 %idx.i, %len.i
53  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
54
55in.bounds.i:                                      ; preds = %loop.i
56  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
57  store i32 0, i32* %addr.i
58  %next.i = icmp slt i32 %idx.next.i, %n
59  br i1 %next.i, label %loop.i, label %exit.i
60
61out.of.bounds.i:                                  ; preds = %loop.i
62  br label %inner_loop.exit
63
64exit.i:                                           ; preds = %in.bounds.i, %loop
65  br label %inner_loop.exit
66
67inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
68  br i1 %next, label %loop, label %exit
69
70exit:                                             ; preds = %inner_loop.exit
71  ret void
72}
73
74; Function Attrs: alwaysinline
75define void @with_grandparent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
76; CHECK: irce: in function with_grandparent: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
77
78entry:
79  br label %loop
80
81loop:                                             ; preds = %with_parent.exit, %entry
82  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
83  %idx.next = add i32 %idx, 1
84  %next = icmp ult i32 %idx.next, %grandparent.count
85  br label %loop.i
86
87loop.i:                                           ; preds = %inner_loop.exit.i, %loop
88  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
89  %idx.next.i = add i32 %idx.i, 1
90  %next.i = icmp ult i32 %idx.next.i, %parent.count
91  %len.i.i = load i32, i32* %a_len_ptr, !range !0
92  %first.itr.check.i.i = icmp sgt i32 %n, 0
93  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
94
95loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
96  %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
97  %idx.next.i.i = add i32 %idx.i.i, 1
98  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
99  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
100
101in.bounds.i.i:                                    ; preds = %loop.i.i
102  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
103  store i32 0, i32* %addr.i.i
104  %next.i.i = icmp slt i32 %idx.next.i.i, %n
105  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
106
107out.of.bounds.i.i:                                ; preds = %loop.i.i
108  br label %inner_loop.exit.i
109
110exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
111  br label %inner_loop.exit.i
112
113inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
114  br i1 %next.i, label %loop.i, label %with_parent.exit
115
116with_parent.exit:                                 ; preds = %inner_loop.exit.i
117  br i1 %next, label %loop, label %exit
118
119exit:                                             ; preds = %with_parent.exit
120  ret void
121}
122
123; Function Attrs: alwaysinline
124define void @with_sibling(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
125; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
126; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i6<header><exiting>,%in.bounds.i9<latch><exiting>
127
128entry:
129  br label %loop
130
131loop:                                             ; preds = %inner_loop.exit12, %entry
132  %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit12 ]
133  %idx.next = add i32 %idx, 1
134  %next = icmp ult i32 %idx.next, %parent.count
135  %len.i = load i32, i32* %a_len_ptr, !range !0
136  %first.itr.check.i = icmp sgt i32 %n, 0
137  br i1 %first.itr.check.i, label %loop.i, label %exit.i
138
139loop.i:                                           ; preds = %in.bounds.i, %loop
140  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
141  %idx.next.i = add i32 %idx.i, 1
142  %abc.i = icmp slt i32 %idx.i, %len.i
143  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
144
145in.bounds.i:                                      ; preds = %loop.i
146  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
147  store i32 0, i32* %addr.i
148  %next.i = icmp slt i32 %idx.next.i, %n
149  br i1 %next.i, label %loop.i, label %exit.i
150
151out.of.bounds.i:                                  ; preds = %loop.i
152  br label %inner_loop.exit
153
154exit.i:                                           ; preds = %in.bounds.i, %loop
155  br label %inner_loop.exit
156
157inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
158  %len.i1 = load i32, i32* %a_len_ptr, !range !0
159  %first.itr.check.i2 = icmp sgt i32 %n, 0
160  br i1 %first.itr.check.i2, label %loop.i6, label %exit.i11
161
162loop.i6:                                          ; preds = %in.bounds.i9, %inner_loop.exit
163  %idx.i3 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i4, %in.bounds.i9 ]
164  %idx.next.i4 = add i32 %idx.i3, 1
165  %abc.i5 = icmp slt i32 %idx.i3, %len.i1
166  br i1 %abc.i5, label %in.bounds.i9, label %out.of.bounds.i10, !prof !1
167
168in.bounds.i9:                                     ; preds = %loop.i6
169  %addr.i7 = getelementptr i32, i32* %arr, i32 %idx.i3
170  store i32 0, i32* %addr.i7
171  %next.i8 = icmp slt i32 %idx.next.i4, %n
172  br i1 %next.i8, label %loop.i6, label %exit.i11
173
174out.of.bounds.i10:                                ; preds = %loop.i6
175  br label %inner_loop.exit12
176
177exit.i11:                                         ; preds = %in.bounds.i9, %inner_loop.exit
178  br label %inner_loop.exit12
179
180inner_loop.exit12:                                ; preds = %exit.i11, %out.of.bounds.i10
181  br i1 %next, label %loop, label %exit
182
183exit:                                             ; preds = %inner_loop.exit12
184  ret void
185}
186
187; Function Attrs: alwaysinline
188define void @with_cousin(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
189; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
190; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i10<header><exiting>,%in.bounds.i.i13<latch><exiting>
191
192entry:
193  br label %loop
194
195loop:                                             ; preds = %with_parent.exit17, %entry
196  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit17 ]
197  %idx.next = add i32 %idx, 1
198  %next = icmp ult i32 %idx.next, %grandparent.count
199  br label %loop.i
200
201loop.i:                                           ; preds = %inner_loop.exit.i, %loop
202  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
203  %idx.next.i = add i32 %idx.i, 1
204  %next.i = icmp ult i32 %idx.next.i, %parent.count
205  %len.i.i = load i32, i32* %a_len_ptr, !range !0
206  %first.itr.check.i.i = icmp sgt i32 %n, 0
207  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
208
209loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
210  %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
211  %idx.next.i.i = add i32 %idx.i.i, 1
212  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
213  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
214
215in.bounds.i.i:                                    ; preds = %loop.i.i
216  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
217  store i32 0, i32* %addr.i.i
218  %next.i.i = icmp slt i32 %idx.next.i.i, %n
219  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
220
221out.of.bounds.i.i:                                ; preds = %loop.i.i
222  br label %inner_loop.exit.i
223
224exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
225  br label %inner_loop.exit.i
226
227inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
228  br i1 %next.i, label %loop.i, label %with_parent.exit
229
230with_parent.exit:                                 ; preds = %inner_loop.exit.i
231  br label %loop.i6
232
233loop.i6:                                          ; preds = %inner_loop.exit.i16, %with_parent.exit
234  %idx.i1 = phi i32 [ 0, %with_parent.exit ], [ %idx.next.i2, %inner_loop.exit.i16 ]
235  %idx.next.i2 = add i32 %idx.i1, 1
236  %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
237  %len.i.i4 = load i32, i32* %a_len_ptr, !range !0
238  %first.itr.check.i.i5 = icmp sgt i32 %n, 0
239  br i1 %first.itr.check.i.i5, label %loop.i.i10, label %exit.i.i15
240
241loop.i.i10:                                       ; preds = %in.bounds.i.i13, %loop.i6
242  %idx.i.i7 = phi i32 [ 0, %loop.i6 ], [ %idx.next.i.i8, %in.bounds.i.i13 ]
243  %idx.next.i.i8 = add i32 %idx.i.i7, 1
244  %abc.i.i9 = icmp slt i32 %idx.i.i7, %len.i.i4
245  br i1 %abc.i.i9, label %in.bounds.i.i13, label %out.of.bounds.i.i14, !prof !1
246
247in.bounds.i.i13:                                  ; preds = %loop.i.i10
248  %addr.i.i11 = getelementptr i32, i32* %arr, i32 %idx.i.i7
249  store i32 0, i32* %addr.i.i11
250  %next.i.i12 = icmp slt i32 %idx.next.i.i8, %n
251  br i1 %next.i.i12, label %loop.i.i10, label %exit.i.i15
252
253out.of.bounds.i.i14:                              ; preds = %loop.i.i10
254  br label %inner_loop.exit.i16
255
256exit.i.i15:                                       ; preds = %in.bounds.i.i13, %loop.i6
257  br label %inner_loop.exit.i16
258
259inner_loop.exit.i16:                              ; preds = %exit.i.i15, %out.of.bounds.i.i14
260  br i1 %next.i3, label %loop.i6, label %with_parent.exit17
261
262with_parent.exit17:                               ; preds = %inner_loop.exit.i16
263  br i1 %next, label %loop, label %exit
264
265exit:                                             ; preds = %with_parent.exit17
266  ret void
267}
268
269; Function Attrs: alwaysinline
270define void @with_uncle(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
271; CHECK: irce: in function with_uncle: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
272; CHECK: irce: in function with_uncle: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
273
274entry:
275  br label %loop
276
277loop:                                             ; preds = %with_parent.exit, %entry
278  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
279  %idx.next = add i32 %idx, 1
280  %next = icmp ult i32 %idx.next, %grandparent.count
281  %len.i = load i32, i32* %a_len_ptr, !range !0
282  %first.itr.check.i = icmp sgt i32 %n, 0
283  br i1 %first.itr.check.i, label %loop.i, label %exit.i
284
285loop.i:                                           ; preds = %in.bounds.i, %loop
286  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
287  %idx.next.i = add i32 %idx.i, 1
288  %abc.i = icmp slt i32 %idx.i, %len.i
289  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
290
291in.bounds.i:                                      ; preds = %loop.i
292  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
293  store i32 0, i32* %addr.i
294  %next.i = icmp slt i32 %idx.next.i, %n
295  br i1 %next.i, label %loop.i, label %exit.i
296
297out.of.bounds.i:                                  ; preds = %loop.i
298  br label %inner_loop.exit
299
300exit.i:                                           ; preds = %in.bounds.i, %loop
301  br label %inner_loop.exit
302
303inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
304  br label %loop.i4
305
306loop.i4:                                          ; preds = %inner_loop.exit.i, %inner_loop.exit
307  %idx.i1 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i2, %inner_loop.exit.i ]
308  %idx.next.i2 = add i32 %idx.i1, 1
309  %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
310  %len.i.i = load i32, i32* %a_len_ptr, !range !0
311  %first.itr.check.i.i = icmp sgt i32 %n, 0
312  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
313
314loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i4
315  %idx.i.i = phi i32 [ 0, %loop.i4 ], [ %idx.next.i.i, %in.bounds.i.i ]
316  %idx.next.i.i = add i32 %idx.i.i, 1
317  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
318  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
319
320in.bounds.i.i:                                    ; preds = %loop.i.i
321  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
322  store i32 0, i32* %addr.i.i
323  %next.i.i = icmp slt i32 %idx.next.i.i, %n
324  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
325
326out.of.bounds.i.i:                                ; preds = %loop.i.i
327  br label %inner_loop.exit.i
328
329exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i4
330  br label %inner_loop.exit.i
331
332inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
333  br i1 %next.i3, label %loop.i4, label %with_parent.exit
334
335with_parent.exit:                                 ; preds = %inner_loop.exit.i
336  br i1 %next, label %loop, label %exit
337
338exit:                                             ; preds = %with_parent.exit
339  ret void
340}
341
342attributes #0 = { alwaysinline }
343
344!0 = !{i32 0, i32 2147483647}
345!1 = !{!"branch_weights", i32 64, i32 4}
346