1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
2 ; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
4 ; Check that we can remove trivially non-failing range check.
5 define i32 @test_increasing_slt_slt_wide_simple_no_postloop() {
7 ; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_no_postloop(
11 ; CHECK: br i1 true, label %backedge, label %check_failed
17 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
18 %rc = icmp slt i64 %iv, 100
19 br i1 %rc, label %backedge, label %check_failed
22 %iv.next = add i64 %iv, 1
23 %narrow.iv = trunc i64 %iv.next to i32
24 %latch.cond = icmp slt i32 %narrow.iv, 100
25 br i1 %latch.cond, label %loop, label %exit
34 ; This range check fails on the last iteration, so it needs a postloop.
35 define i32 @test_increasing_slt_slt_wide_simple_postloop() {
37 ; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_postloop(
40 ; CHECK: br i1 true, label %backedge, label %check_failed
42 ; CHECK: [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, 99
43 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
50 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
51 %rc = icmp slt i64 %iv, 99
52 br i1 %rc, label %backedge, label %check_failed
55 %iv.next = add i64 %iv, 1
56 %narrow.iv = trunc i64 %iv.next to i32
57 %latch.cond = icmp slt i32 %narrow.iv, 100
58 br i1 %latch.cond, label %loop, label %exit
67 ; General case. If both %N and %M are non-negative, we do not need a preloop.
68 define i32 @test_increasing_slt_slt_wide_non-negative(i32* %n_ptr, i64* %m_ptr) {
70 ; CHECK-LABEL: @test_increasing_slt_slt_wide_non-negative(
73 ; CHECK: br i1 true, label %backedge, label %check_failed
75 ; CHECK: [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, %exit.mainloop.at
76 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
80 %N = load i32, i32* %n_ptr, !range !2
81 %M = load i64, i64* %m_ptr, !range !1
85 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
86 %rc = icmp slt i64 %iv, %M
87 br i1 %rc, label %backedge, label %check_failed
90 %iv.next = add i64 %iv, 1
91 %narrow.iv = trunc i64 %iv.next to i32
92 %latch.cond = icmp slt i32 %narrow.iv, %N
93 br i1 %latch.cond, label %loop, label %exit
102 ; General case. Even though %M may be negative, we do not need a preloop because
103 ; we make a non-negativity runtime check against M and do not go to main loop if
105 define i32 @test_increasing_slt_slt_wide_general(i32* %n_ptr, i64* %m_ptr) {
107 ; CHECK-LABEL: @test_increasing_slt_slt_wide_general(
110 ; CHECK: br i1 true, label %backedge, label %check_failed
112 ; CHECK: [[COND:%[^ ]+]] = icmp slt i64
113 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
117 %N = load i32, i32* %n_ptr, !range !2
118 %M = load i64, i64* %m_ptr
122 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
123 %rc = icmp slt i64 %iv, %M
124 br i1 %rc, label %backedge, label %check_failed
127 %iv.next = add i64 %iv, 1
128 %narrow.iv = trunc i64 %iv.next to i32
129 %latch.cond = icmp slt i32 %narrow.iv, %N
130 br i1 %latch.cond, label %loop, label %exit
139 ; General case with preloop.
140 define i32 @test_increasing_slt_slt_wide_general_preloop(i32* %n_ptr, i64* %m_ptr) {
142 ; CHECK-LABEL: @test_increasing_slt_slt_wide_general_preloop(
144 ; CHECK: br i1 true, label %backedge, label %check_failed
146 ; CHECK: [[COND:%[^ ]+]] = icmp slt i64
147 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
152 %N = load i32, i32* %n_ptr, !range !2
153 %M = load i64, i64* %m_ptr
157 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
158 %rc = icmp slt i64 %iv, %M
159 br i1 %rc, label %backedge, label %check_failed
162 %iv.next = add i64 %iv, 1
163 %narrow.iv = trunc i64 %iv to i32
164 %latch.cond = icmp slt i32 %narrow.iv, %N
165 br i1 %latch.cond, label %loop, label %exit
174 ; Same as above, multiple checks.
175 define i32 @test_increasing_slt_slt_wide_multiple_checks(i32* %n_ptr, i64* %m1_ptr, i64* %m2_ptr, i64* %m3_ptr, i64* %m4_ptr) {
176 ; CHECK-LABEL: @test_increasing_slt_slt_wide_multiple_checks(
179 ; CHECK: %c1 = and i1 true, true
180 ; CHECK: %c2 = and i1 %c1, true
181 ; CHECK: %rc = and i1 %c2, true
182 ; CHECK: br i1 %rc, label %backedge, label %check_failed.loopexit
184 ; CHECK: [[COND:%[^ ]+]] = icmp slt i64
185 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
189 %N = load i32, i32* %n_ptr, !range !2
190 %M1 = load i64, i64* %m1_ptr
191 %M2 = load i64, i64* %m2_ptr
192 %M3 = load i64, i64* %m3_ptr
193 %M4 = load i64, i64* %m4_ptr
197 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
198 %rc1 = icmp slt i64 %iv, %M1
199 %rc2 = icmp slt i64 %iv, %M2
200 %rc3 = icmp slt i64 %iv, %M3
201 %rc4 = icmp slt i64 %iv, %M4
202 %c1 = and i1 %rc1, %rc2
203 %c2 = and i1 %c1, %rc3
204 %rc = and i1 %c2, %rc4
205 br i1 %rc, label %backedge, label %check_failed
208 %iv.next = add i64 %iv, 1
209 %narrow.iv = trunc i64 %iv.next to i32
210 %latch.cond = icmp slt i32 %narrow.iv, %N
211 br i1 %latch.cond, label %loop, label %exit
220 ; Wide IV against narrow range check. We don't currently support it.
221 define i32 @test_increasing_slt_slt_wide_simple_negtest_narrow_rc() {
223 ; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_negtest_narrow_rc(
231 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
232 %narrow.iv = trunc i64 %iv to i32
233 %rc = icmp slt i32 %narrow.iv, 101
234 br i1 %rc, label %backedge, label %check_failed
237 %iv.next = add i64 %iv, 1
238 %latch.cond = icmp slt i64 %iv, 100
239 br i1 %latch.cond, label %loop, label %exit
248 ; Check that we can remove trivially non-failing range check.
249 define i32 @test_increasing_ult_ult_wide_simple_no_postloop() {
251 ; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_no_postloop(
253 ; CHECK-NOT: postloop
255 ; CHECK: br i1 true, label %backedge, label %check_failed
261 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
262 %rc = icmp ult i64 %iv, 100
263 br i1 %rc, label %backedge, label %check_failed
266 %iv.next = add i64 %iv, 1
267 %narrow.iv = trunc i64 %iv.next to i32
268 %latch.cond = icmp ult i32 %narrow.iv, 100
269 br i1 %latch.cond, label %loop, label %exit
278 ; This range check fails on the last iteration, so it needs a postloop.
279 define i32 @test_increasing_ult_ult_wide_simple_postloop() {
281 ; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_postloop(
284 ; CHECK: br i1 true, label %backedge, label %check_failed
286 ; CHECK: [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, 99
287 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
294 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
295 %rc = icmp ult i64 %iv, 99
296 br i1 %rc, label %backedge, label %check_failed
299 %iv.next = add i64 %iv, 1
300 %narrow.iv = trunc i64 %iv.next to i32
301 %latch.cond = icmp ult i32 %narrow.iv, 100
302 br i1 %latch.cond, label %loop, label %exit
311 ; General case. If both %N and %M are non-negative, we do not need a preloop.
312 define i32 @test_increasing_ult_ult_wide_non-negative(i32* %n_ptr, i64* %m_ptr) {
314 ; CHECK-LABEL: @test_increasing_ult_ult_wide_non-negative(
317 ; CHECK: br i1 true, label %backedge, label %check_failed
319 ; CHECK: [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, %exit.mainloop.at
320 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
324 %N = load i32, i32* %n_ptr, !range !2
325 %M = load i64, i64* %m_ptr, !range !1
329 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
330 %rc = icmp ult i64 %iv, %M
331 br i1 %rc, label %backedge, label %check_failed
334 %iv.next = add i64 %iv, 1
335 %narrow.iv = trunc i64 %iv.next to i32
336 %latch.cond = icmp ult i32 %narrow.iv, %N
337 br i1 %latch.cond, label %loop, label %exit
346 ; General case. Even though %M may be negative, we do not need a preloop because
347 ; we make a non-negativity runtime check against M and do not go to main loop if
349 define i32 @test_increasing_ult_ult_wide_general(i32* %n_ptr, i64* %m_ptr) {
351 ; CHECK-LABEL: @test_increasing_ult_ult_wide_general(
354 ; CHECK: br i1 true, label %backedge, label %check_failed
356 ; CHECK: [[COND:%[^ ]+]] = icmp ult i64
357 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
361 %N = load i32, i32* %n_ptr, !range !2
362 %M = load i64, i64* %m_ptr
366 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
367 %rc = icmp ult i64 %iv, %M
368 br i1 %rc, label %backedge, label %check_failed
371 %iv.next = add i64 %iv, 1
372 %narrow.iv = trunc i64 %iv.next to i32
373 %latch.cond = icmp ult i32 %narrow.iv, %N
374 br i1 %latch.cond, label %loop, label %exit
383 ; Same as above, multiple checks.
384 define i32 @test_increasing_ult_ult_wide_multiple_checks(i32* %n_ptr, i64* %m1_ptr, i64* %m2_ptr, i64* %m3_ptr, i64* %m4_ptr) {
385 ; CHECK-LABEL: @test_increasing_ult_ult_wide_multiple_checks(
388 ; CHECK: %c1 = and i1 true, true
389 ; CHECK: %c2 = and i1 %c1, true
390 ; CHECK: %rc = and i1 %c2, true
391 ; CHECK: br i1 %rc, label %backedge, label %check_failed.loopexit
393 ; CHECK: [[COND:%[^ ]+]] = icmp ult i64
394 ; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
398 %N = load i32, i32* %n_ptr, !range !2
399 %M1 = load i64, i64* %m1_ptr
400 %M2 = load i64, i64* %m2_ptr
401 %M3 = load i64, i64* %m3_ptr
402 %M4 = load i64, i64* %m4_ptr
406 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
407 %rc1 = icmp ult i64 %iv, %M1
408 %rc2 = icmp ult i64 %iv, %M2
409 %rc3 = icmp ult i64 %iv, %M3
410 %rc4 = icmp ult i64 %iv, %M4
411 %c1 = and i1 %rc1, %rc2
412 %c2 = and i1 %c1, %rc3
413 %rc = and i1 %c2, %rc4
414 br i1 %rc, label %backedge, label %check_failed
417 %iv.next = add i64 %iv, 1
418 %narrow.iv = trunc i64 %iv.next to i32
419 %latch.cond = icmp ult i32 %narrow.iv, %N
420 br i1 %latch.cond, label %loop, label %exit
429 ; Wide IV against narrow range check. We don't currently support it.
430 define i32 @test_increasing_ult_ult_wide_simple_negtest_narrow_rc() {
432 ; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_negtest_narrow_rc(
440 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
441 %narrow.iv = trunc i64 %iv to i32
442 %rc = icmp ult i32 %narrow.iv, 101
443 br i1 %rc, label %backedge, label %check_failed
446 %iv.next = add i64 %iv, 1
447 %latch.cond = icmp ult i64 %iv, 100
448 br i1 %latch.cond, label %loop, label %exit
457 !0 = !{i32 0, i32 2147483647}
458 !1 = !{i64 0, i64 9223372036854775807}
459 !2 = !{i32 1, i32 2147483647}