1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
2 ; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
4 ; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
5 ; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
6 ; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7 ; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
8 ; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9 ; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
10 ; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
11 ; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
12 ; CHECK-NOT: irce: in function test_09: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
14 ; ULT condition for increasing loop.
15 define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
19 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
20 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
21 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
23 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
24 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
25 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
26 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
27 ; CHECK-NOT: loop.preloop:
28 ; CHECK: loop.postloop:
29 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
30 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
31 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
32 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
35 %len = load i32, i32* %a_len_ptr, !range !0
39 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
40 %idx.next = add nsw nuw i32 %idx, 1
41 %abc = icmp ult i32 %idx, %len
42 br i1 %abc, label %in.bounds, label %out.of.bounds
45 %addr = getelementptr i32, i32* %arr, i32 %idx
46 store i32 0, i32* %addr
47 %next = icmp ult i32 %idx.next, 100
48 br i1 %next, label %loop, label %exit
57 ; ULT condition for decreasing loops.
58 define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
62 ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0
63 ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
64 ; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1
65 ; CHECK-NEXT: %exit.preloop.at = add nsw i32 [[UMIN]], -1
66 ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at
67 ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
69 ; CHECK-NEXT: br label %loop
71 ; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
72 ; CHECK-NEXT: %idx.next = add i32 %idx, -1
73 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %len
74 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
75 ; CHECK-NOT: loop.postloop:
76 ; CHECK: loop.preloop:
77 ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
78 ; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -1
79 ; CHECK-NEXT: %abc.preloop = icmp ult i32 %idx.preloop, %len
80 ; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
83 %len = load i32, i32* %a_len_ptr, !range !0
87 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
88 %idx.next = add i32 %idx, -1
89 %abc = icmp ult i32 %idx, %len
90 br i1 %abc, label %in.bounds, label %out.of.bounds
93 %addr = getelementptr i32, i32* %arr, i32 %idx
94 store i32 0, i32* %addr
95 %next = icmp ult i32 %idx.next, 1
96 br i1 %next, label %exit, label %loop
106 define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
110 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
111 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
112 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
114 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
115 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
116 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
117 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
118 ; CHECK-NOT: loop.preloop:
119 ; CHECK: loop.postloop:
120 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
121 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
122 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
123 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
126 %len = load i32, i32* %a_len_ptr, !range !0
130 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
131 %idx.next = add nsw nuw i32 %idx, 1
132 %abc = icmp ult i32 %idx, %len
133 br i1 %abc, label %in.bounds, label %out.of.bounds
136 %addr = getelementptr i32, i32* %arr, i32 %idx
137 store i32 0, i32* %addr
138 %next = icmp ult i32 %idx.next, 2147483647
139 br i1 %next, label %loop, label %exit
148 ; Check SINT_MAX + 1, test is similar to test_01.
149 define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
153 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
154 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
155 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
157 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
158 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
159 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
160 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
161 ; CHECK-NOT: loop.preloop:
162 ; CHECK: loop.postloop:
163 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
164 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
165 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
166 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
169 %len = load i32, i32* %a_len_ptr, !range !0
173 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
174 %idx.next = add nsw nuw i32 %idx, 1
175 %abc = icmp ult i32 %idx, %len
176 br i1 %abc, label %in.bounds, label %out.of.bounds
179 %addr = getelementptr i32, i32* %arr, i32 %idx
180 store i32 0, i32* %addr
181 %next = icmp ult i32 %idx.next, 2147483648
182 br i1 %next, label %loop, label %exit
191 ; Check SINT_MAX + 1, test is similar to test_02.
192 define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
195 ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0
196 ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
197 ; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1
198 ; CHECK-NEXT: %exit.preloop.at = add nsw i32 [[UMIN]], -1
199 ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at
200 ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
202 ; CHECK-NEXT: br label %loop
204 ; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
205 ; CHECK-NEXT: %idx.next = add i32 %idx, -1
206 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %len
207 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
208 ; CHECK-NOT: loop.postloop:
209 ; CHECK: loop.preloop:
210 ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -2147483648, %loop.preloop.preheader ]
211 ; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -1
212 ; CHECK-NEXT: %abc.preloop = icmp ult i32 %idx.preloop, %len
213 ; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
216 %len = load i32, i32* %a_len_ptr, !range !0
220 %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
221 %idx.next = add i32 %idx, -1
222 %abc = icmp ult i32 %idx, %len
223 br i1 %abc, label %in.bounds, label %out.of.bounds
226 %addr = getelementptr i32, i32* %arr, i32 %idx
227 store i32 0, i32* %addr
228 %next = icmp ult i32 %idx.next, 1
229 br i1 %next, label %exit, label %loop
238 ; Increasing loop, UINT_MAX. Positive test.
239 define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
243 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
244 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
245 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
247 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
248 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
249 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
250 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
251 ; CHECK-NOT: loop.preloop:
252 ; CHECK: loop.postloop:
253 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
254 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
255 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
256 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
259 %len = load i32, i32* %a_len_ptr, !range !0
263 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
264 %idx.next = add nsw nuw i32 %idx, 1
265 %abc = icmp ult i32 %idx, %len
266 br i1 %abc, label %in.bounds, label %out.of.bounds
269 %addr = getelementptr i32, i32* %arr, i32 %idx
270 store i32 0, i32* %addr
271 %next = icmp ult i32 %idx.next, 4294967295
272 br i1 %next, label %loop, label %exit
281 ; Decreasing loop, UINT_MAX. Negative test: we cannot substract -1 from 0.
282 define void @test_07(i32* %arr, i32* %a_len_ptr) #0 {
285 ; CHECK-NOT: loop.preloop:
286 ; CHECK-NOT: loop.postloop:
289 %len = load i32, i32* %a_len_ptr, !range !0
293 %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
294 %idx.next = add nuw i32 %idx, -1
295 %abc = icmp ult i32 %idx, %len
296 br i1 %abc, label %in.bounds, label %out.of.bounds
299 %addr = getelementptr i32, i32* %arr, i32 %idx
300 store i32 0, i32* %addr
301 %next = icmp ult i32 %idx.next, 0
302 br i1 %next, label %exit, label %loop
311 ; Unsigned walking through signed border is allowed.
312 ; Iteration space [0; UINT_MAX - 99), the fact that SINT_MAX is within this
313 ; range does not prevent us from performing IRCE.
315 define void @test_08(i32* %arr, i32* %a_len_ptr) #0 {
319 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
320 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
321 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
323 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
324 ; CHECK-NEXT: %idx.next = add i32 %idx, 1
325 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
326 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
327 ; CHECK-NOT: loop.preloop:
328 ; CHECK: loop.postloop:
329 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
330 ; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1
331 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
332 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
335 %len = load i32, i32* %a_len_ptr, !range !0
339 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
340 %idx.next = add i32 %idx, 1
341 %abc = icmp ult i32 %idx, %len
342 br i1 %abc, label %in.bounds, label %out.of.bounds
345 %addr = getelementptr i32, i32* %arr, i32 %idx
346 store i32 0, i32* %addr
347 %next = icmp ult i32 %idx.next, -100
348 br i1 %next, label %loop, label %exit
357 ; Walking through the border of unsigned range is not allowed
358 ; (iteration space [-100; 100)). Negative test.
360 define void @test_09(i32* %arr, i32* %a_len_ptr) #0 {
364 ; CHECK-NOT: postloop
365 ; CHECK-NOT: br i1 false
366 ; CHECK-NOT: br i1 true
369 %len = load i32, i32* %a_len_ptr, !range !0
373 %idx = phi i32 [ -100, %entry ], [ %idx.next, %in.bounds ]
374 %idx.next = add i32 %idx, 1
375 %abc = icmp ult i32 %idx, %len
376 br i1 %abc, label %in.bounds, label %out.of.bounds
379 %addr = getelementptr i32, i32* %arr, i32 %idx
380 store i32 0, i32* %addr
381 %next = icmp ult i32 %idx.next, 100
382 br i1 %next, label %loop, label %exit
391 !0 = !{i32 0, i32 50}