1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
2 ; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' < %s 2>&1 | FileCheck %s
4 ; This test checks if we update the LoopInfo correctly in the presence
5 ; of parents, uncles and cousins.
7 ; Function Attrs: alwaysinline
8 define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 {
9 ; CHECK: irce: in function inner_loop: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
12 %len = load i32, i32* %a_len_ptr, !range !0
13 %first.itr.check = icmp sgt i32 %n, 0
14 br i1 %first.itr.check, label %loop, label %exit
16 loop: ; preds = %in.bounds, %entry
17 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
18 %idx.next = add i32 %idx, 1
19 %abc = icmp slt i32 %idx, %len
20 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
22 in.bounds: ; preds = %loop
23 %addr = getelementptr i32, i32* %arr, i32 %idx
24 store i32 0, i32* %addr
25 %next = icmp slt i32 %idx.next, %n
26 br i1 %next, label %loop, label %exit
28 out.of.bounds: ; preds = %loop
31 exit: ; preds = %in.bounds, %entry
35 ; Function Attrs: alwaysinline
36 define void @with_parent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
37 ; CHECK: irce: in function with_parent: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
42 loop: ; preds = %inner_loop.exit, %entry
43 %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit ]
44 %idx.next = add i32 %idx, 1
45 %next = icmp ult i32 %idx.next, %parent.count
46 %len.i = load i32, i32* %a_len_ptr, !range !0
47 %first.itr.check.i = icmp sgt i32 %n, 0
48 br i1 %first.itr.check.i, label %loop.i, label %exit.i
50 loop.i: ; preds = %in.bounds.i, %loop
51 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
52 %idx.next.i = add i32 %idx.i, 1
53 %abc.i = icmp slt i32 %idx.i, %len.i
54 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
56 in.bounds.i: ; preds = %loop.i
57 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
58 store i32 0, i32* %addr.i
59 %next.i = icmp slt i32 %idx.next.i, %n
60 br i1 %next.i, label %loop.i, label %exit.i
62 out.of.bounds.i: ; preds = %loop.i
63 br label %inner_loop.exit
65 exit.i: ; preds = %in.bounds.i, %loop
66 br label %inner_loop.exit
68 inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i
69 br i1 %next, label %loop, label %exit
71 exit: ; preds = %inner_loop.exit
75 ; Function Attrs: alwaysinline
76 define void @with_grandparent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
77 ; CHECK: irce: in function with_grandparent: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
82 loop: ; preds = %with_parent.exit, %entry
83 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
84 %idx.next = add i32 %idx, 1
85 %next = icmp ult i32 %idx.next, %grandparent.count
88 loop.i: ; preds = %inner_loop.exit.i, %loop
89 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
90 %idx.next.i = add i32 %idx.i, 1
91 %next.i = icmp ult i32 %idx.next.i, %parent.count
92 %len.i.i = load i32, i32* %a_len_ptr, !range !0
93 %first.itr.check.i.i = icmp sgt i32 %n, 0
94 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
96 loop.i.i: ; preds = %in.bounds.i.i, %loop.i
97 %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
98 %idx.next.i.i = add i32 %idx.i.i, 1
99 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
100 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
102 in.bounds.i.i: ; preds = %loop.i.i
103 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
104 store i32 0, i32* %addr.i.i
105 %next.i.i = icmp slt i32 %idx.next.i.i, %n
106 br i1 %next.i.i, label %loop.i.i, label %exit.i.i
108 out.of.bounds.i.i: ; preds = %loop.i.i
109 br label %inner_loop.exit.i
111 exit.i.i: ; preds = %in.bounds.i.i, %loop.i
112 br label %inner_loop.exit.i
114 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
115 br i1 %next.i, label %loop.i, label %with_parent.exit
117 with_parent.exit: ; preds = %inner_loop.exit.i
118 br i1 %next, label %loop, label %exit
120 exit: ; preds = %with_parent.exit
124 ; Function Attrs: alwaysinline
125 define void @with_sibling(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
126 ; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
127 ; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i6<header><exiting>,%in.bounds.i9<latch><exiting>
132 loop: ; preds = %inner_loop.exit12, %entry
133 %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit12 ]
134 %idx.next = add i32 %idx, 1
135 %next = icmp ult i32 %idx.next, %parent.count
136 %len.i = load i32, i32* %a_len_ptr, !range !0
137 %first.itr.check.i = icmp sgt i32 %n, 0
138 br i1 %first.itr.check.i, label %loop.i, label %exit.i
140 loop.i: ; preds = %in.bounds.i, %loop
141 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
142 %idx.next.i = add i32 %idx.i, 1
143 %abc.i = icmp slt i32 %idx.i, %len.i
144 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
146 in.bounds.i: ; preds = %loop.i
147 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
148 store i32 0, i32* %addr.i
149 %next.i = icmp slt i32 %idx.next.i, %n
150 br i1 %next.i, label %loop.i, label %exit.i
152 out.of.bounds.i: ; preds = %loop.i
153 br label %inner_loop.exit
155 exit.i: ; preds = %in.bounds.i, %loop
156 br label %inner_loop.exit
158 inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i
159 %len.i1 = load i32, i32* %a_len_ptr, !range !0
160 %first.itr.check.i2 = icmp sgt i32 %n, 0
161 br i1 %first.itr.check.i2, label %loop.i6, label %exit.i11
163 loop.i6: ; preds = %in.bounds.i9, %inner_loop.exit
164 %idx.i3 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i4, %in.bounds.i9 ]
165 %idx.next.i4 = add i32 %idx.i3, 1
166 %abc.i5 = icmp slt i32 %idx.i3, %len.i1
167 br i1 %abc.i5, label %in.bounds.i9, label %out.of.bounds.i10, !prof !1
169 in.bounds.i9: ; preds = %loop.i6
170 %addr.i7 = getelementptr i32, i32* %arr, i32 %idx.i3
171 store i32 0, i32* %addr.i7
172 %next.i8 = icmp slt i32 %idx.next.i4, %n
173 br i1 %next.i8, label %loop.i6, label %exit.i11
175 out.of.bounds.i10: ; preds = %loop.i6
176 br label %inner_loop.exit12
178 exit.i11: ; preds = %in.bounds.i9, %inner_loop.exit
179 br label %inner_loop.exit12
181 inner_loop.exit12: ; preds = %exit.i11, %out.of.bounds.i10
182 br i1 %next, label %loop, label %exit
184 exit: ; preds = %inner_loop.exit12
188 ; Function Attrs: alwaysinline
189 define void @with_cousin(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
190 ; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
191 ; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i10<header><exiting>,%in.bounds.i.i13<latch><exiting>
196 loop: ; preds = %with_parent.exit17, %entry
197 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit17 ]
198 %idx.next = add i32 %idx, 1
199 %next = icmp ult i32 %idx.next, %grandparent.count
202 loop.i: ; preds = %inner_loop.exit.i, %loop
203 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
204 %idx.next.i = add i32 %idx.i, 1
205 %next.i = icmp ult i32 %idx.next.i, %parent.count
206 %len.i.i = load i32, i32* %a_len_ptr, !range !0
207 %first.itr.check.i.i = icmp sgt i32 %n, 0
208 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
210 loop.i.i: ; preds = %in.bounds.i.i, %loop.i
211 %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
212 %idx.next.i.i = add i32 %idx.i.i, 1
213 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
214 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
216 in.bounds.i.i: ; preds = %loop.i.i
217 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
218 store i32 0, i32* %addr.i.i
219 %next.i.i = icmp slt i32 %idx.next.i.i, %n
220 br i1 %next.i.i, label %loop.i.i, label %exit.i.i
222 out.of.bounds.i.i: ; preds = %loop.i.i
223 br label %inner_loop.exit.i
225 exit.i.i: ; preds = %in.bounds.i.i, %loop.i
226 br label %inner_loop.exit.i
228 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
229 br i1 %next.i, label %loop.i, label %with_parent.exit
231 with_parent.exit: ; preds = %inner_loop.exit.i
234 loop.i6: ; preds = %inner_loop.exit.i16, %with_parent.exit
235 %idx.i1 = phi i32 [ 0, %with_parent.exit ], [ %idx.next.i2, %inner_loop.exit.i16 ]
236 %idx.next.i2 = add i32 %idx.i1, 1
237 %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
238 %len.i.i4 = load i32, i32* %a_len_ptr, !range !0
239 %first.itr.check.i.i5 = icmp sgt i32 %n, 0
240 br i1 %first.itr.check.i.i5, label %loop.i.i10, label %exit.i.i15
242 loop.i.i10: ; preds = %in.bounds.i.i13, %loop.i6
243 %idx.i.i7 = phi i32 [ 0, %loop.i6 ], [ %idx.next.i.i8, %in.bounds.i.i13 ]
244 %idx.next.i.i8 = add i32 %idx.i.i7, 1
245 %abc.i.i9 = icmp slt i32 %idx.i.i7, %len.i.i4
246 br i1 %abc.i.i9, label %in.bounds.i.i13, label %out.of.bounds.i.i14, !prof !1
248 in.bounds.i.i13: ; preds = %loop.i.i10
249 %addr.i.i11 = getelementptr i32, i32* %arr, i32 %idx.i.i7
250 store i32 0, i32* %addr.i.i11
251 %next.i.i12 = icmp slt i32 %idx.next.i.i8, %n
252 br i1 %next.i.i12, label %loop.i.i10, label %exit.i.i15
254 out.of.bounds.i.i14: ; preds = %loop.i.i10
255 br label %inner_loop.exit.i16
257 exit.i.i15: ; preds = %in.bounds.i.i13, %loop.i6
258 br label %inner_loop.exit.i16
260 inner_loop.exit.i16: ; preds = %exit.i.i15, %out.of.bounds.i.i14
261 br i1 %next.i3, label %loop.i6, label %with_parent.exit17
263 with_parent.exit17: ; preds = %inner_loop.exit.i16
264 br i1 %next, label %loop, label %exit
266 exit: ; preds = %with_parent.exit17
270 ; Function Attrs: alwaysinline
271 define void @with_uncle(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
272 ; CHECK: irce: in function with_uncle: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
273 ; CHECK: irce: in function with_uncle: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
278 loop: ; preds = %with_parent.exit, %entry
279 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
280 %idx.next = add i32 %idx, 1
281 %next = icmp ult i32 %idx.next, %grandparent.count
282 %len.i = load i32, i32* %a_len_ptr, !range !0
283 %first.itr.check.i = icmp sgt i32 %n, 0
284 br i1 %first.itr.check.i, label %loop.i, label %exit.i
286 loop.i: ; preds = %in.bounds.i, %loop
287 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
288 %idx.next.i = add i32 %idx.i, 1
289 %abc.i = icmp slt i32 %idx.i, %len.i
290 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
292 in.bounds.i: ; preds = %loop.i
293 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
294 store i32 0, i32* %addr.i
295 %next.i = icmp slt i32 %idx.next.i, %n
296 br i1 %next.i, label %loop.i, label %exit.i
298 out.of.bounds.i: ; preds = %loop.i
299 br label %inner_loop.exit
301 exit.i: ; preds = %in.bounds.i, %loop
302 br label %inner_loop.exit
304 inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i
307 loop.i4: ; preds = %inner_loop.exit.i, %inner_loop.exit
308 %idx.i1 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i2, %inner_loop.exit.i ]
309 %idx.next.i2 = add i32 %idx.i1, 1
310 %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
311 %len.i.i = load i32, i32* %a_len_ptr, !range !0
312 %first.itr.check.i.i = icmp sgt i32 %n, 0
313 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
315 loop.i.i: ; preds = %in.bounds.i.i, %loop.i4
316 %idx.i.i = phi i32 [ 0, %loop.i4 ], [ %idx.next.i.i, %in.bounds.i.i ]
317 %idx.next.i.i = add i32 %idx.i.i, 1
318 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
319 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
321 in.bounds.i.i: ; preds = %loop.i.i
322 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
323 store i32 0, i32* %addr.i.i
324 %next.i.i = icmp slt i32 %idx.next.i.i, %n
325 br i1 %next.i.i, label %loop.i.i, label %exit.i.i
327 out.of.bounds.i.i: ; preds = %loop.i.i
328 br label %inner_loop.exit.i
330 exit.i.i: ; preds = %in.bounds.i.i, %loop.i4
331 br label %inner_loop.exit.i
333 inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i
334 br i1 %next.i3, label %loop.i4, label %with_parent.exit
336 with_parent.exit: ; preds = %inner_loop.exit.i
337 br i1 %next, label %loop, label %exit
339 exit: ; preds = %with_parent.exit
343 attributes #0 = { alwaysinline }
345 !0 = !{i32 0, i32 2147483647}
346 !1 = !{!"branch_weights", i32 64, i32 4}