1 ; RUN: opt -passes=irce -S -verify-loop-info -irce-print-changed-loops -irce-skip-profitability-checks < %s 2>&1 | FileCheck %s
3 ; CHECK: irce: in function test_inc_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
4 ; CHECK: irce: in function test_inc_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
5 ; CHECK: irce: in function test_inc_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
6 ; CHECK: irce: in function test_inc_ult: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
7 ; CHECK: irce: in function signed_var_imm_dec_sgt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
8 ; CHECK-NOT: irce: in function signed_var_imm_dec_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
9 ; CHECK: irce: in function signed_var_imm_dec_sge: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
10 ; CHECK: irce: in function signed_var_imm_dec_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
11 ; CHECK-NOT: irce: in function signed_var_imm_dec_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
12 ; CHECK-NOT: irce: in function test_dec_bound_with_smaller_start_than_bound: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.dec<latch><exiting>
13 ; CHECK-NOT: irce: in function test_inc_bound_with_bigger_start_than_bound: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.dec<latch><exiting>
15 ; CHECK-LABEL: test_inc_eq(
16 ; CHECK: main.exit.selector:
17 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
18 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
19 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
20 define void @test_inc_eq(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %N) {
22 %cmp16 = icmp sgt i32 %N, 0
23 br i1 %cmp16, label %for.body, label %for.cond.cleanup
29 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
30 %cmp1 = icmp ult i32 %i.017, 512
31 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.017
32 %0 = load i32, ptr %arrayidx, align 4
33 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %i.017
34 %1 = load i32, ptr %arrayidx2, align 4
35 br i1 %cmp1, label %if.then, label %if.else
39 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %i.017
40 %2 = load i32, ptr %arrayidx3, align 4
41 %add = add nsw i32 %sub, %2
42 store i32 %add, ptr %arrayidx3, align 4
46 %add6 = add nsw i32 %1, %0
47 %arrayidx7 = getelementptr inbounds i32, ptr %a, i32 %i.017
48 store i32 %add6, ptr %arrayidx7, align 4
52 %inc = add nuw nsw i32 %i.017, 1
53 %exitcond = icmp eq i32 %inc, %N
54 br i1 %exitcond, label %for.cond.cleanup, label %for.body
57 ; CHECK-LABEL: test_inc_ne
58 ; CHECK: main.exit.selector:
59 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
60 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
61 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
62 define void @test_inc_ne(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %N) {
64 %cmp16 = icmp sgt i32 %N, 0
65 br i1 %cmp16, label %for.body, label %for.cond.cleanup
71 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
72 %cmp1 = icmp ult i32 %i.017, 512
73 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.017
74 %0 = load i32, ptr %arrayidx, align 4
75 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %i.017
76 %1 = load i32, ptr %arrayidx2, align 4
77 br i1 %cmp1, label %if.then, label %if.else
81 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %i.017
82 %2 = load i32, ptr %arrayidx3, align 4
83 %add = add nsw i32 %sub, %2
84 store i32 %add, ptr %arrayidx3, align 4
88 %add6 = add nsw i32 %1, %0
89 %arrayidx7 = getelementptr inbounds i32, ptr %a, i32 %i.017
90 store i32 %add6, ptr %arrayidx7, align 4
94 %inc = add nuw nsw i32 %i.017, 1
95 %exitcond = icmp ne i32 %inc, %N
96 br i1 %exitcond, label %for.body, label %for.cond.cleanup
99 ; CHECK-LABEL: test_inc_slt(
100 ; CHECK: main.exit.selector:
101 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
102 ; CHECK: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], %N
103 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
104 define void @test_inc_slt(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %N) {
106 %cmp16 = icmp sgt i32 %N, 0
107 br i1 %cmp16, label %for.body, label %for.cond.cleanup
113 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
114 %cmp1 = icmp ult i32 %i.017, 512
115 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.017
116 %0 = load i32, ptr %arrayidx, align 4
117 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %i.017
118 %1 = load i32, ptr %arrayidx2, align 4
119 br i1 %cmp1, label %if.then, label %if.else
122 %sub = sub i32 %0, %1
123 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %i.017
124 %2 = load i32, ptr %arrayidx3, align 4
125 %add = add nsw i32 %sub, %2
126 store i32 %add, ptr %arrayidx3, align 4
130 %add6 = add nsw i32 %1, %0
131 %arrayidx7 = getelementptr inbounds i32, ptr %a, i32 %i.017
132 store i32 %add6, ptr %arrayidx7, align 4
136 %inc = add nuw nsw i32 %i.017, 1
137 %exitcond = icmp slt i32 %inc, %N
138 br i1 %exitcond, label %for.body, label %for.cond.cleanup
141 ; CHECK-LABEL: test_inc_ult
142 ; CHECK: main.exit.selector:
143 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
144 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
145 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
146 define void @test_inc_ult(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %N) {
148 %cmp16 = icmp ugt i32 %N, 0
149 br i1 %cmp16, label %for.body, label %for.cond.cleanup
155 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
156 %cmp1 = icmp ult i32 %i.017, 512
157 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.017
158 %0 = load i32, ptr %arrayidx, align 4
159 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %i.017
160 %1 = load i32, ptr %arrayidx2, align 4
161 br i1 %cmp1, label %if.then, label %if.else
164 %sub = sub i32 %0, %1
165 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %i.017
166 %2 = load i32, ptr %arrayidx3, align 4
167 %add = add nsw i32 %sub, %2
168 store i32 %add, ptr %arrayidx3, align 4
172 %add6 = add nsw i32 %1, %0
173 %arrayidx7 = getelementptr inbounds i32, ptr %a, i32 %i.017
174 store i32 %add6, ptr %arrayidx7, align 4
178 %inc = add nuw nsw i32 %i.017, 1
179 %exitcond = icmp ult i32 %inc, %N
180 br i1 %exitcond, label %for.body, label %for.cond.cleanup
183 ; CHECK-LABEL: signed_var_imm_dec_sgt(
184 ; CHECK: main.exit.selector:
185 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ]
186 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
187 ; CHECK: br i1 [[COND]]
188 define void @signed_var_imm_dec_sgt(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %M) {
190 %cmp14 = icmp slt i32 %M, 1024
191 br i1 %cmp14, label %for.body, label %for.cond.cleanup
193 for.cond.cleanup: ; preds = %for.inc, %entry
196 for.body: ; preds = %entry, %for.inc
197 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
198 %cmp1 = icmp slt i32 %iv, 1024
199 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %iv
200 %0 = load i32, ptr %arrayidx, align 4
201 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %iv
202 %1 = load i32, ptr %arrayidx2, align 4
203 %mul = mul nsw i32 %1, %0
204 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %iv
205 br i1 %cmp1, label %for.inc, label %if.else
207 if.else: ; preds = %for.body
208 %2 = load i32, ptr %arrayidx3, align 4
209 %add = add nsw i32 %2, %mul
212 for.inc: ; preds = %for.body, %if.else
213 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
214 store i32 %storemerge, ptr %arrayidx3, align 4
215 %dec = add nsw i32 %iv, -1
216 %cmp = icmp sgt i32 %dec, %M
217 br i1 %cmp, label %for.body, label %for.cond.cleanup
220 ; CHECK-LABEL: signed_var_imm_dec_sge(
221 ; CHECK: main.exit.selector: ; preds = %for.inc
222 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %iv, %for.inc ]
223 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
224 ; CHECK: br i1 [[COND]]
225 define void @signed_var_imm_dec_sge(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %M) {
227 %cmp14 = icmp sgt i32 %M, 1024
228 br i1 %cmp14, label %for.cond.cleanup, label %for.body
230 for.cond.cleanup: ; preds = %for.inc, %entry
233 for.body: ; preds = %entry, %for.inc
234 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
235 %cmp1 = icmp slt i32 %iv, 1024
236 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %iv
237 %0 = load i32, ptr %arrayidx, align 4
238 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %iv
239 %1 = load i32, ptr %arrayidx2, align 4
240 %mul = mul nsw i32 %1, %0
241 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %iv
242 br i1 %cmp1, label %for.inc, label %if.else
244 if.else: ; preds = %for.body
245 %2 = load i32, ptr %arrayidx3, align 4
246 %add = add nsw i32 %2, %mul
249 for.inc: ; preds = %for.body, %if.else
250 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
251 store i32 %storemerge, ptr %arrayidx3, align 4
252 %dec = add nsw i32 %iv, -1
253 %cmp = icmp sgt i32 %iv, %M
254 br i1 %cmp, label %for.body, label %for.cond.cleanup
257 define void @signed_var_imm_dec_slt(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %M) {
259 %cmp14 = icmp sgt i32 %M, 1024
260 br i1 %cmp14, label %for.cond.cleanup, label %for.body
262 for.cond.cleanup: ; preds = %for.inc, %entry
265 for.body: ; preds = %entry, %for.inc
266 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
267 %cmp1 = icmp slt i32 %iv, 1024
268 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %iv
269 %0 = load i32, ptr %arrayidx, align 4
270 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %iv
271 %1 = load i32, ptr %arrayidx2, align 4
272 %mul = mul nsw i32 %1, %0
273 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %iv
274 br i1 %cmp1, label %for.inc, label %if.else
276 if.else: ; preds = %for.body
277 %2 = load i32, ptr %arrayidx3, align 4
278 %add = add nsw i32 %2, %mul
281 for.inc: ; preds = %for.body, %if.else
282 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
283 store i32 %storemerge, ptr %arrayidx3, align 4
284 %dec = add nsw i32 %iv, -1
285 %cmp = icmp slt i32 %iv, %M
286 br i1 %cmp, label %for.cond.cleanup, label %for.body
289 ; CHECK-LABEL: signed_var_imm_dec_ne(
290 ; CHECK: main.exit.selector: ; preds = %for.inc
291 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ]
292 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
293 ; CHECK: br i1 [[COND]]
294 define void @signed_var_imm_dec_ne(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %M) {
296 %cmp14 = icmp slt i32 %M, 1024
297 br i1 %cmp14, label %for.body, label %for.cond.cleanup
299 for.cond.cleanup: ; preds = %for.inc, %entry
302 for.body: ; preds = %entry, %for.inc
303 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
304 %cmp1 = icmp slt i32 %iv, 1024
305 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %iv
306 %0 = load i32, ptr %arrayidx, align 4
307 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %iv
308 %1 = load i32, ptr %arrayidx2, align 4
309 %mul = mul nsw i32 %1, %0
310 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %iv
311 br i1 %cmp1, label %for.inc, label %if.else
313 if.else: ; preds = %for.body
314 %2 = load i32, ptr %arrayidx3, align 4
315 %add = add nsw i32 %2, %mul
318 for.inc: ; preds = %for.body, %if.else
319 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
320 store i32 %storemerge, ptr %arrayidx3, align 4
321 %dec = add nsw i32 %iv, -1
322 %cmp = icmp ne i32 %dec, %M
323 br i1 %cmp, label %for.body, label %for.cond.cleanup
326 define void @signed_var_imm_dec_eq(ptr nocapture %a, ptr nocapture readonly %b, ptr nocapture readonly %c, i32 %M) {
328 %cmp14 = icmp slt i32 %M, 1024
329 br i1 %cmp14, label %for.body, label %for.cond.cleanup
331 for.cond.cleanup: ; preds = %for.inc, %entry
334 for.body: ; preds = %entry, %for.inc
335 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
336 %cmp1 = icmp slt i32 %iv, 1024
337 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %iv
338 %0 = load i32, ptr %arrayidx, align 4
339 %arrayidx2 = getelementptr inbounds i32, ptr %c, i32 %iv
340 %1 = load i32, ptr %arrayidx2, align 4
341 %mul = mul nsw i32 %1, %0
342 %arrayidx3 = getelementptr inbounds i32, ptr %a, i32 %iv
343 br i1 %cmp1, label %for.inc, label %if.else
345 if.else: ; preds = %for.body
346 %2 = load i32, ptr %arrayidx3, align 4
347 %add = add nsw i32 %2, %mul
350 for.inc: ; preds = %for.body, %if.else
351 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
352 store i32 %storemerge, ptr %arrayidx3, align 4
353 %dec = add nsw i32 %iv, -1
354 %cmp = icmp eq i32 %dec, %M
355 br i1 %cmp, label %for.cond.cleanup, label %for.body
358 ; CHECK-LABEL: @test_dec_bound_with_smaller_start_than_bound(
359 ; CHECK-NOT: preloop.exit.selector:
360 define void @test_dec_bound_with_smaller_start_than_bound(i64 %0) {
364 for.body: ; preds = %for.dec, %entry
365 %iv = phi i64 [ %dec, %for.dec ], [ 0, %entry ]
366 %1 = icmp slt i64 %iv, %0
367 br i1 %1, label %if.else, label %for.dec
369 if.else: ; preds = %for.body
372 for.dec: ; preds = %if.else, %for.body
373 %dec = sub nuw nsw i64 %iv, 1
374 %2 = icmp slt i64 %dec, 1
375 br i1 %2, label %exit, label %for.body
377 exit: ; preds = %for.dec
381 ; CHECK-LABEL: @test_inc_bound_with_bigger_start_than_bound(
382 ; CHECK-NOT: main.exit.selector:
383 define void @test_inc_bound_with_bigger_start_than_bound(i32 %0) {
387 for.body: ; preds = %for.inc, %entry
388 %iv = phi i32 [ %inc, %for.inc ], [ 200, %entry ]
389 %1 = icmp slt i32 %iv, %0
390 br i1 %1, label %if.else, label %for.inc
392 if.else: ; preds = %for.body
395 for.inc: ; preds = %if.else, %for.body
396 %inc = add nsw i32 %iv, 1
397 %2 = icmp sgt i32 %inc, 100
398 br i1 %2, label %exit, label %for.body
400 exit: ; preds = %for.inc