Teach IRCE to look at branch weights when recognizing range checks
[oota-llvm.git] / test / Transforms / IRCE / with-parent-loops.ll
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
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>
9
10 entry:
11   %len = load 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
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
20
21 in.bounds:                                        ; preds = %loop
22   %addr = getelementptr 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
27 out.of.bounds:                                    ; preds = %loop
28   ret void
29
30 exit:                                             ; preds = %in.bounds, %entry
31   ret void
32 }
33
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>
37
38 entry:
39   br label %loop
40
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* %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
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
54
55 in.bounds.i:                                      ; preds = %loop.i
56   %addr.i = getelementptr 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
61 out.of.bounds.i:                                  ; preds = %loop.i
62   br label %inner_loop.exit
63
64 exit.i:                                           ; preds = %in.bounds.i, %loop
65   br label %inner_loop.exit
66
67 inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
68   br i1 %next, label %loop, label %exit
69
70 exit:                                             ; preds = %inner_loop.exit
71   ret void
72 }
73
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>
77
78 entry:
79   br label %loop
80
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
85   br label %loop.i
86
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* %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
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
100
101 in.bounds.i.i:                                    ; preds = %loop.i.i
102   %addr.i.i = getelementptr 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
107 out.of.bounds.i.i:                                ; preds = %loop.i.i
108   br label %inner_loop.exit.i
109
110 exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
111   br label %inner_loop.exit.i
112
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
115
116 with_parent.exit:                                 ; preds = %inner_loop.exit.i
117   br i1 %next, label %loop, label %exit
118
119 exit:                                             ; preds = %with_parent.exit
120   ret void
121 }
122
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>
127
128 entry:
129   br label %loop
130
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* %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
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
144
145 in.bounds.i:                                      ; preds = %loop.i
146   %addr.i = getelementptr 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
151 out.of.bounds.i:                                  ; preds = %loop.i
152   br label %inner_loop.exit
153
154 exit.i:                                           ; preds = %in.bounds.i, %loop
155   br label %inner_loop.exit
156
157 inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
158   %len.i1 = load 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
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
167
168 in.bounds.i9:                                     ; preds = %loop.i6
169   %addr.i7 = getelementptr 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
174 out.of.bounds.i10:                                ; preds = %loop.i6
175   br label %inner_loop.exit12
176
177 exit.i11:                                         ; preds = %in.bounds.i9, %inner_loop.exit
178   br label %inner_loop.exit12
179
180 inner_loop.exit12:                                ; preds = %exit.i11, %out.of.bounds.i10
181   br i1 %next, label %loop, label %exit
182
183 exit:                                             ; preds = %inner_loop.exit12
184   ret void
185 }
186
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>
191
192 entry:
193   br label %loop
194
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
199   br label %loop.i
200
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* %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
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
214
215 in.bounds.i.i:                                    ; preds = %loop.i.i
216   %addr.i.i = getelementptr 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
221 out.of.bounds.i.i:                                ; preds = %loop.i.i
222   br label %inner_loop.exit.i
223
224 exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
225   br label %inner_loop.exit.i
226
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
229
230 with_parent.exit:                                 ; preds = %inner_loop.exit.i
231   br label %loop.i6
232
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* %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
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
246
247 in.bounds.i.i13:                                  ; preds = %loop.i.i10
248   %addr.i.i11 = getelementptr 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
253 out.of.bounds.i.i14:                              ; preds = %loop.i.i10
254   br label %inner_loop.exit.i16
255
256 exit.i.i15:                                       ; preds = %in.bounds.i.i13, %loop.i6
257   br label %inner_loop.exit.i16
258
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
261
262 with_parent.exit17:                               ; preds = %inner_loop.exit.i16
263   br i1 %next, label %loop, label %exit
264
265 exit:                                             ; preds = %with_parent.exit17
266   ret void
267 }
268
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>
273
274 entry:
275   br label %loop
276
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* %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
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
290
291 in.bounds.i:                                      ; preds = %loop.i
292   %addr.i = getelementptr 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
297 out.of.bounds.i:                                  ; preds = %loop.i
298   br label %inner_loop.exit
299
300 exit.i:                                           ; preds = %in.bounds.i, %loop
301   br label %inner_loop.exit
302
303 inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
304   br label %loop.i4
305
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* %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
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
319
320 in.bounds.i.i:                                    ; preds = %loop.i.i
321   %addr.i.i = getelementptr 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
326 out.of.bounds.i.i:                                ; preds = %loop.i.i
327   br label %inner_loop.exit.i
328
329 exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i4
330   br label %inner_loop.exit.i
331
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
334
335 with_parent.exit:                                 ; preds = %inner_loop.exit.i
336   br i1 %next, label %loop, label %exit
337
338 exit:                                             ; preds = %with_parent.exit
339   ret void
340 }
341
342 attributes #0 = { alwaysinline }
343
344 !0 = !{i32 0, i32 2147483647}
345 !1 = !{!"branch_weights", i32 64, i32 4}