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-NOT: 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>
11 ; UGT condition for increasing loop.
12 define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
16 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
17 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
18 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
20 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
21 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
22 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
23 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
24 ; CHECK-NOT: loop.preloop:
25 ; CHECK: loop.postloop:
26 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
27 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
28 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
29 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
32 %len = load i32, i32* %a_len_ptr, !range !0
36 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
37 %idx.next = add nsw nuw i32 %idx, 1
38 %abc = icmp ult i32 %idx, %len
39 br i1 %abc, label %in.bounds, label %out.of.bounds
42 %addr = getelementptr i32, i32* %arr, i32 %idx
43 store i32 0, i32* %addr
44 %next = icmp ugt i32 %idx.next, 100
45 br i1 %next, label %exit, label %loop
54 ; UGT condition for decreasing loop.
55 define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
59 ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0
60 ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
61 ; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1
62 ; CHECK-NEXT: %exit.preloop.at = add nsw i32 [[UMIN]], -1
63 ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at
64 ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
66 ; CHECK-NEXT: br label %loop
68 ; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
69 ; CHECK-NEXT: %idx.next = add i32 %idx, -1
70 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %len
71 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
72 ; CHECK-NOT: loop.postloop:
73 ; CHECK: loop.preloop:
74 ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
75 ; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -1
76 ; CHECK-NEXT: %abc.preloop = icmp ult i32 %idx.preloop, %len
77 ; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
80 %len = load i32, i32* %a_len_ptr, !range !0
84 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
85 %idx.next = add i32 %idx, -1
86 %abc = icmp ult i32 %idx, %len
87 br i1 %abc, label %in.bounds, label %out.of.bounds
90 %addr = getelementptr i32, i32* %arr, i32 %idx
91 store i32 0, i32* %addr
92 %next = icmp ugt i32 %idx.next, 0
93 br i1 %next, label %loop, label %exit
102 ; Check SINT_MAX + 1, test is similar to test_01.
103 define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
107 ; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
108 ; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
109 ; CHECK-NEXT: br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
111 ; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
112 ; CHECK-NEXT: %idx.next = add nuw nsw i32 %idx, 1
113 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %exit.mainloop.at
114 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
115 ; CHECK-NOT: loop.preloop:
116 ; CHECK: loop.postloop:
117 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
118 ; CHECK-NEXT: %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
119 ; CHECK-NEXT: %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
120 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
123 %len = load i32, i32* %a_len_ptr, !range !0
127 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
128 %idx.next = add nsw nuw i32 %idx, 1
129 %abc = icmp ult i32 %idx, %len
130 br i1 %abc, label %in.bounds, label %out.of.bounds
133 %addr = getelementptr i32, i32* %arr, i32 %idx
134 store i32 0, i32* %addr
135 %next = icmp ugt i32 %idx.next, 2147483648
136 br i1 %next, label %exit, label %loop
145 ; Check SINT_MAX + 1, test is similar to test_02.
146 define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
150 ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0
151 ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
152 ; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1
153 ; CHECK-NEXT: %exit.preloop.at = add nsw i32 [[UMIN]], -1
154 ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at
155 ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
157 ; CHECK-NEXT: br label %loop
159 ; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
160 ; CHECK-NEXT: %idx.next = add i32 %idx, -1
161 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %len
162 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
163 ; CHECK-NOT: loop.postloop:
164 ; CHECK: loop.preloop:
165 ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -2147483648, %loop.preloop.preheader ]
166 ; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -1
167 ; CHECK-NEXT: %abc.preloop = icmp ult i32 %idx.preloop, %len
168 ; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
171 %len = load i32, i32* %a_len_ptr, !range !0
175 %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
176 %idx.next = add i32 %idx, -1
177 %abc = icmp ult i32 %idx, %len
178 br i1 %abc, label %in.bounds, label %out.of.bounds
181 %addr = getelementptr i32, i32* %arr, i32 %idx
182 store i32 0, i32* %addr
183 %next = icmp ugt i32 %idx.next, 0
184 br i1 %next, label %loop, label %exit
193 ; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.
194 define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
197 ; CHECK-NOT: loop.preloop:
198 ; CHECK-NOT: loop.postloop:
201 %len = load i32, i32* %a_len_ptr, !range !0
205 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
206 %idx.next = add nsw nuw i32 %idx, 1
207 %abc = icmp ult i32 %idx, %len
208 br i1 %abc, label %in.bounds, label %out.of.bounds
211 %addr = getelementptr i32, i32* %arr, i32 %idx
212 store i32 0, i32* %addr
213 %next = icmp ugt i32 %idx.next, 4294967295
214 br i1 %next, label %exit, label %loop
223 ; Decreasing loop, UINT_MAX. Positive test.
224 define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
228 ; CHECK-NEXT: br label %loop
230 ; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
231 ; CHECK-NEXT: %idx.next = add nuw i32 %idx, -1
232 ; CHECK-NEXT: %abc = icmp ult i32 %idx, %len
233 ; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
234 ; CHECK-NOT: loop.postloop:
235 ; CHECK: loop.preloop:
236 ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -1, %loop.preloop.preheader ]
237 ; CHECK-NEXT: %idx.next.preloop = add nuw i32 %idx.preloop, -1
238 ; CHECK-NEXT: %abc.preloop = icmp ult i32 %idx.preloop, %len
239 ; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
242 %len = load i32, i32* %a_len_ptr, !range !0
246 %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
247 %idx.next = add nuw i32 %idx, -1
248 %abc = icmp ult i32 %idx, %len
249 br i1 %abc, label %in.bounds, label %out.of.bounds
252 %addr = getelementptr i32, i32* %arr, i32 %idx
253 store i32 0, i32* %addr
254 %next = icmp ugt i32 %idx.next, 0
255 br i1 %next, label %loop, label %exit
264 !0 = !{i32 0, i32 50}