1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
3 ; This test checks if we update the LoopInfo correctly in the presence
4 ; of parents, uncles and cousins.
6 ; Function Attrs: alwaysinline
7 define 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>
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
15 loop: ; 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
21 in.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
27 out.of.bounds: ; preds = %loop
30 exit: ; preds = %in.bounds, %entry
34 ; Function Attrs: alwaysinline
35 define 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>
41 loop: ; 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
49 loop.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
55 in.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
61 out.of.bounds.i: ; preds = %loop.i
62 br label %inner_loop.exit
64 exit.i: ; preds = %in.bounds.i, %loop
65 br label %inner_loop.exit
67 inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i
68 br i1 %next, label %loop, label %exit
70 exit: ; preds = %inner_loop.exit
74 ; Function Attrs: alwaysinline
75 define 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>
81 loop: ; 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
87 loop.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
95 loop.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
101 in.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
107 out.of.bounds.i.i: ; preds = %loop.i.i
108 br label %inner_loop.exit.i
110 exit.i.i: ; preds = %in.bounds.i.i, %loop.i
111 br label %inner_loop.exit.i
113 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
114 br i1 %next.i, label %loop.i, label %with_parent.exit
116 with_parent.exit: ; preds = %inner_loop.exit.i
117 br i1 %next, label %loop, label %exit
119 exit: ; preds = %with_parent.exit
123 ; Function Attrs: alwaysinline
124 define 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>
131 loop: ; 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
139 loop.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
145 in.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
151 out.of.bounds.i: ; preds = %loop.i
152 br label %inner_loop.exit
154 exit.i: ; preds = %in.bounds.i, %loop
155 br label %inner_loop.exit
157 inner_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
162 loop.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
168 in.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
174 out.of.bounds.i10: ; preds = %loop.i6
175 br label %inner_loop.exit12
177 exit.i11: ; preds = %in.bounds.i9, %inner_loop.exit
178 br label %inner_loop.exit12
180 inner_loop.exit12: ; preds = %exit.i11, %out.of.bounds.i10
181 br i1 %next, label %loop, label %exit
183 exit: ; preds = %inner_loop.exit12
187 ; Function Attrs: alwaysinline
188 define 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>
195 loop: ; 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
201 loop.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
209 loop.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
215 in.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
221 out.of.bounds.i.i: ; preds = %loop.i.i
222 br label %inner_loop.exit.i
224 exit.i.i: ; preds = %in.bounds.i.i, %loop.i
225 br label %inner_loop.exit.i
227 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
228 br i1 %next.i, label %loop.i, label %with_parent.exit
230 with_parent.exit: ; preds = %inner_loop.exit.i
233 loop.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
241 loop.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
247 in.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
253 out.of.bounds.i.i14: ; preds = %loop.i.i10
254 br label %inner_loop.exit.i16
256 exit.i.i15: ; preds = %in.bounds.i.i13, %loop.i6
257 br label %inner_loop.exit.i16
259 inner_loop.exit.i16: ; preds = %exit.i.i15, %out.of.bounds.i.i14
260 br i1 %next.i3, label %loop.i6, label %with_parent.exit17
262 with_parent.exit17: ; preds = %inner_loop.exit.i16
263 br i1 %next, label %loop, label %exit
265 exit: ; preds = %with_parent.exit17
269 ; Function Attrs: alwaysinline
270 define 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>
277 loop: ; 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
285 loop.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
291 in.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
297 out.of.bounds.i: ; preds = %loop.i
298 br label %inner_loop.exit
300 exit.i: ; preds = %in.bounds.i, %loop
301 br label %inner_loop.exit
303 inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i
306 loop.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
314 loop.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
320 in.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
326 out.of.bounds.i.i: ; preds = %loop.i.i
327 br label %inner_loop.exit.i
329 exit.i.i: ; preds = %in.bounds.i.i, %loop.i4
330 br label %inner_loop.exit.i
332 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
333 br i1 %next.i3, label %loop.i4, label %with_parent.exit
335 with_parent.exit: ; preds = %inner_loop.exit.i
336 br i1 %next, label %loop, label %exit
338 exit: ; preds = %with_parent.exit
342 attributes #0 = { alwaysinline }
344 !0 = !{i32 0, i32 2147483647}
345 !1 = !{!"branch_weights", i32 64, i32 4}