1; RUN: opt -irce -S -verify-loop-info -irce-print-changed-loops -irce-skip-profitability-checks < %s 2>&1 | FileCheck %s
2
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>
14
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
20define void @test_inc_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
21entry:
22  %cmp16 = icmp sgt i32 %N, 0
23  br i1 %cmp16, label %for.body, label %for.cond.cleanup
24
25for.cond.cleanup:
26  ret void
27
28for.body:
29  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
30  %cmp1 = icmp ult i32 %i.017, 512
31  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
32  %0 = load i32, i32* %arrayidx, align 4
33  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
34  %1 = load i32, i32* %arrayidx2, align 4
35  br i1 %cmp1, label %if.then, label %if.else
36
37if.then:
38  %sub = sub i32 %0, %1
39  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
40  %2 = load i32, i32* %arrayidx3, align 4
41  %add = add nsw i32 %sub, %2
42  store i32 %add, i32* %arrayidx3, align 4
43  br label %for.inc
44
45if.else:
46  %add6 = add nsw i32 %1, %0
47  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
48  store i32 %add6, i32* %arrayidx7, align 4
49  br label %for.inc
50
51for.inc:
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
55}
56
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
62define void @test_inc_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
63entry:
64  %cmp16 = icmp sgt i32 %N, 0
65  br i1 %cmp16, label %for.body, label %for.cond.cleanup
66
67for.cond.cleanup:
68  ret void
69
70for.body:
71  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
72  %cmp1 = icmp ult i32 %i.017, 512
73  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
74  %0 = load i32, i32* %arrayidx, align 4
75  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
76  %1 = load i32, i32* %arrayidx2, align 4
77  br i1 %cmp1, label %if.then, label %if.else
78
79if.then:
80  %sub = sub i32 %0, %1
81  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
82  %2 = load i32, i32* %arrayidx3, align 4
83  %add = add nsw i32 %sub, %2
84  store i32 %add, i32* %arrayidx3, align 4
85  br label %for.inc
86
87if.else:
88  %add6 = add nsw i32 %1, %0
89  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
90  store i32 %add6, i32* %arrayidx7, align 4
91  br label %for.inc
92
93for.inc:
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
97}
98
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
104define void @test_inc_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
105entry:
106  %cmp16 = icmp sgt i32 %N, 0
107  br i1 %cmp16, label %for.body, label %for.cond.cleanup
108
109for.cond.cleanup:
110  ret void
111
112for.body:
113  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
114  %cmp1 = icmp ult i32 %i.017, 512
115  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
116  %0 = load i32, i32* %arrayidx, align 4
117  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
118  %1 = load i32, i32* %arrayidx2, align 4
119  br i1 %cmp1, label %if.then, label %if.else
120
121if.then:
122  %sub = sub i32 %0, %1
123  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
124  %2 = load i32, i32* %arrayidx3, align 4
125  %add = add nsw i32 %sub, %2
126  store i32 %add, i32* %arrayidx3, align 4
127  br label %for.inc
128
129if.else:
130  %add6 = add nsw i32 %1, %0
131  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
132  store i32 %add6, i32* %arrayidx7, align 4
133  br label %for.inc
134
135for.inc:
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
139}
140
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
146define void @test_inc_ult(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
147entry:
148  %cmp16 = icmp ugt i32 %N, 0
149  br i1 %cmp16, label %for.body, label %for.cond.cleanup
150
151for.cond.cleanup:
152  ret void
153
154for.body:
155  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
156  %cmp1 = icmp ult i32 %i.017, 512
157  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
158  %0 = load i32, i32* %arrayidx, align 4
159  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
160  %1 = load i32, i32* %arrayidx2, align 4
161  br i1 %cmp1, label %if.then, label %if.else
162
163if.then:
164  %sub = sub i32 %0, %1
165  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
166  %2 = load i32, i32* %arrayidx3, align 4
167  %add = add nsw i32 %sub, %2
168  store i32 %add, i32* %arrayidx3, align 4
169  br label %for.inc
170
171if.else:
172  %add6 = add nsw i32 %1, %0
173  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
174  store i32 %add6, i32* %arrayidx7, align 4
175  br label %for.inc
176
177for.inc:
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
181}
182
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]]
188define void @signed_var_imm_dec_sgt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
189entry:
190  %cmp14 = icmp slt i32 %M, 1024
191  br i1 %cmp14, label %for.body, label %for.cond.cleanup
192
193for.cond.cleanup:                                 ; preds = %for.inc, %entry
194  ret void
195
196for.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, i32* %b, i32 %iv
200  %0 = load i32, i32* %arrayidx, align 4
201  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
202  %1 = load i32, i32* %arrayidx2, align 4
203  %mul = mul nsw i32 %1, %0
204  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
205  br i1 %cmp1, label %for.inc, label %if.else
206
207if.else:                                          ; preds = %for.body
208  %2 = load i32, i32* %arrayidx3, align 4
209  %add = add nsw i32 %2, %mul
210  br label %for.inc
211
212for.inc:                                          ; preds = %for.body, %if.else
213  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
214  store i32 %storemerge, i32* %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
218}
219
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]]
225define void @signed_var_imm_dec_sge(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
226entry:
227  %cmp14 = icmp sgt i32 %M, 1024
228  br i1 %cmp14, label %for.cond.cleanup, label %for.body
229
230for.cond.cleanup:                                 ; preds = %for.inc, %entry
231  ret void
232
233for.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, i32* %b, i32 %iv
237  %0 = load i32, i32* %arrayidx, align 4
238  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
239  %1 = load i32, i32* %arrayidx2, align 4
240  %mul = mul nsw i32 %1, %0
241  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
242  br i1 %cmp1, label %for.inc, label %if.else
243
244if.else:                                          ; preds = %for.body
245  %2 = load i32, i32* %arrayidx3, align 4
246  %add = add nsw i32 %2, %mul
247  br label %for.inc
248
249for.inc:                                          ; preds = %for.body, %if.else
250  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
251  store i32 %storemerge, i32* %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
255}
256
257define void @signed_var_imm_dec_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
258entry:
259  %cmp14 = icmp sgt i32 %M, 1024
260  br i1 %cmp14, label %for.cond.cleanup, label %for.body
261
262for.cond.cleanup:                                 ; preds = %for.inc, %entry
263  ret void
264
265for.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, i32* %b, i32 %iv
269  %0 = load i32, i32* %arrayidx, align 4
270  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
271  %1 = load i32, i32* %arrayidx2, align 4
272  %mul = mul nsw i32 %1, %0
273  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
274  br i1 %cmp1, label %for.inc, label %if.else
275
276if.else:                                          ; preds = %for.body
277  %2 = load i32, i32* %arrayidx3, align 4
278  %add = add nsw i32 %2, %mul
279  br label %for.inc
280
281for.inc:                                          ; preds = %for.body, %if.else
282  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
283  store i32 %storemerge, i32* %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
287}
288
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]]
294define void @signed_var_imm_dec_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
295entry:
296  %cmp14 = icmp slt i32 %M, 1024
297  br i1 %cmp14, label %for.body, label %for.cond.cleanup
298
299for.cond.cleanup:                                 ; preds = %for.inc, %entry
300  ret void
301
302for.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, i32* %b, i32 %iv
306  %0 = load i32, i32* %arrayidx, align 4
307  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
308  %1 = load i32, i32* %arrayidx2, align 4
309  %mul = mul nsw i32 %1, %0
310  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
311  br i1 %cmp1, label %for.inc, label %if.else
312
313if.else:                                          ; preds = %for.body
314  %2 = load i32, i32* %arrayidx3, align 4
315  %add = add nsw i32 %2, %mul
316  br label %for.inc
317
318for.inc:                                          ; preds = %for.body, %if.else
319  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
320  store i32 %storemerge, i32* %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
324}
325
326define void @signed_var_imm_dec_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
327entry:
328  %cmp14 = icmp slt i32 %M, 1024
329  br i1 %cmp14, label %for.body, label %for.cond.cleanup
330
331for.cond.cleanup:                                 ; preds = %for.inc, %entry
332  ret void
333
334for.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, i32* %b, i32 %iv
338  %0 = load i32, i32* %arrayidx, align 4
339  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
340  %1 = load i32, i32* %arrayidx2, align 4
341  %mul = mul nsw i32 %1, %0
342  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
343  br i1 %cmp1, label %for.inc, label %if.else
344
345if.else:                                          ; preds = %for.body
346  %2 = load i32, i32* %arrayidx3, align 4
347  %add = add nsw i32 %2, %mul
348  br label %for.inc
349
350for.inc:                                          ; preds = %for.body, %if.else
351  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
352  store i32 %storemerge, i32* %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
356}
357
358; CHECK-LABEL: @test_dec_bound_with_smaller_start_than_bound(
359; CHECK-NOT:       preloop.exit.selector:
360define void @test_dec_bound_with_smaller_start_than_bound(i64 %0) {
361entry:
362  br label %for.body
363
364for.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
368
369if.else:                                                ; preds = %for.body
370  br label %for.dec
371
372for.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
376
377exit:                                               ; preds = %for.dec
378  ret void
379}
380
381; CHECK-LABEL: @test_inc_bound_with_bigger_start_than_bound(
382; CHECK-NOT:       main.exit.selector:
383define void @test_inc_bound_with_bigger_start_than_bound(i32 %0) {
384entry:
385  br label %for.body
386
387for.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
391
392if.else:                                                ; preds = %for.body
393  br label %for.inc
394
395for.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
399
400exit:                                                ; preds = %for.inc
401  ret void
402}
403