1 ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-guard=true -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EXIT
2 ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-guard=true -force-hardware-loop-phi=true -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LATCH
3 ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-guard=false -S %s -o - | FileCheck %s --check-prefix=NO-GUARD
5 ; NO-GUARD-NOT: @llvm.test.set.loop.iterations
9 ; CHECK: [[MAX:%[^ ]+]] = call i32 @llvm.umax.i32(i32 %N, i32 2)
10 ; CHECK: [[COUNT:%[^ ]+]] = add i32 [[MAX]], -1
11 ; CHECK: br i1 %t1, label %do.body.preheader
12 ; CHECK: do.body.preheader:
13 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
14 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]])
15 ; CHECK: br label %do.body
16 define void @test1(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
18 br i1 %t1, label %do.body, label %if.end
20 do.body: ; preds = %do.body, %entry
21 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
22 %a.addr.0 = phi i32* [ %incdec.ptr1, %do.body ], [ %a, %entry ]
23 %i.0 = phi i32 [ %inc, %do.body ], [ 1, %entry ]
24 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
25 %tmp = load i32, i32* %b.addr.0, align 4
26 %incdec.ptr1 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
27 store i32 %tmp, i32* %a.addr.0, align 4
28 %inc = add nuw i32 %i.0, 1
29 %cmp = icmp ult i32 %inc, %N
30 br i1 %cmp, label %do.body, label %if.end
32 if.end: ; preds = %do.body, %entry
37 ; CHECK-NOT: call i1 @llvm.test.set.loop.iterations
38 ; CHECK-NOT: call void @llvm.set.loop.iterations
39 ; CHECK-NOT: call i32 @llvm.start.loop.iterations
40 define void @test2(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
42 br i1 %t1, label %do.body, label %if.end
44 do.body: ; preds = %do.body, %entry
45 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
46 %a.addr.0 = phi i32* [ %incdec.ptr1, %do.body ], [ %a, %entry ]
47 %i.0 = phi i32 [ %add, %do.body ], [ 1, %entry ]
48 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
49 %tmp = load i32, i32* %b.addr.0, align 4
50 %incdec.ptr1 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
51 store i32 %tmp, i32* %a.addr.0, align 4
52 %add = add i32 %i.0, 2
53 %cmp = icmp ult i32 %add, %N
54 br i1 %cmp, label %do.body, label %if.end
56 if.end: ; preds = %do.body, %entry
62 ; CHECK: [[COUNT:%[^ ]+]] = call i32 @llvm.umax.i32(i32 %N, i32 1)
63 ; CHECK: br i1 %brmerge.demorgan, label %do.body.preheader
64 ; CHECK: do.body.preheader:
65 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
66 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]])
67 ; CHECK: br label %do.body
68 define void @test3(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
70 %brmerge.demorgan = and i1 %t1, %t2
71 br i1 %brmerge.demorgan, label %do.body, label %if.end
73 do.body: ; preds = %do.body, %entry
74 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
75 %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
76 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
77 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
78 %tmp = load i32, i32* %b.addr.0, align 4
79 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
80 store i32 %tmp, i32* %a.addr.0, align 4
81 %inc = add nuw i32 %i.0, 1
82 %cmp = icmp ult i32 %inc, %N
83 br i1 %cmp, label %do.body, label %if.end
85 if.end: ; preds = %do.body, %entry
91 ; CHECK-LATCH: br i1 %brmerge.demorgan, label %while.cond
92 ; CHECK-LATCH-NOT: @llvm{{.*}}loop.iterations
93 ; CHECK-EXIT: br i1 %brmerge.demorgan, label %while.cond.preheader
94 ; CHECK-EXIT: while.cond.preheader:
95 ; CHECK-EXIT: [[COUNT:%[^ ]+]] = add i32 %N, 1
96 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
97 ; CHECK-EXIT: br label %while.cond
98 define void @test4(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
100 %brmerge.demorgan = and i1 %t1, %t2
101 br i1 %brmerge.demorgan, label %while.cond, label %if.end
103 while.cond: ; preds = %while.body, %entry
104 %b.addr.0 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %entry ]
105 %a.addr.0 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %entry ]
106 %i.0 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
107 %exitcond = icmp eq i32 %i.0, %N
108 br i1 %exitcond, label %if.end, label %while.body
110 while.body: ; preds = %while.cond
111 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
112 %tmp = load i32, i32* %b.addr.0, align 4
113 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
114 store i32 %tmp, i32* %a.addr.0, align 4
115 %inc = add i32 %i.0, 1
118 if.end: ; preds = %while.cond, %entry
124 ; CHECK: br i1 %or.cond, label %while.body.preheader
125 ; CHECK: while.body.preheader:
126 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N)
127 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N)
128 ; CHECK: br label %while.body
129 define void @test5(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
131 %brmerge.demorgan = and i1 %t1, %t2
132 %cmp6 = icmp ne i32 %N, 0
133 %or.cond = and i1 %brmerge.demorgan, %cmp6
134 br i1 %or.cond, label %while.body, label %if.end
136 while.body: ; preds = %while.body, %entry
137 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
138 %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %entry ]
139 %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %entry ]
140 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
141 %tmp = load i32, i32* %b.addr.07, align 4
142 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
143 store i32 %tmp, i32* %a.addr.08, align 4
144 %inc = add nuw i32 %i.09, 1
145 %exitcond = icmp eq i32 %inc, %N
146 br i1 %exitcond, label %if.end, label %while.body
148 if.end: ; preds = %while.body, %entry
154 ; CHECK: br i1 %brmerge.demorgan, label %while.preheader
155 ; CHECK: while.preheader:
156 ; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
157 ; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N)
158 ; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1
159 ; CHECK: br i1 [[TEST]], label %while.body.preheader, label %if.end
160 ; CHECK: while.body.preheader:
161 ; CHECK: br label %while.body
162 define void @test6(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
164 %brmerge.demorgan = and i1 %t1, %t2
165 br i1 %brmerge.demorgan, label %while.preheader, label %if.end
167 while.preheader: ; preds = %entry
168 %cmp = icmp ne i32 %N, 0
169 br i1 %cmp, label %while.body, label %if.end
171 while.body: ; preds = %while.body, %while.preheader
172 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
173 %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
174 %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
175 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
176 %tmp = load i32, i32* %b.addr.07, align 4
177 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
178 store i32 %tmp, i32* %a.addr.08, align 4
179 %inc = add nuw i32 %i.09, 1
180 %exitcond = icmp eq i32 %inc, %N
181 br i1 %exitcond, label %if.end, label %while.body
183 if.end: ; preds = %while.body, %while.preheader, %entry
189 ; CHECK: br i1 %brmerge.demorgan, label %while.preheader
190 ; CHECK: while.preheader:
191 ; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
192 ; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N)
193 ; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1
194 ; CHECK: br i1 [[TEST]], label %while.body.preheader, label %if.end
195 ; CHECK: while.body.preheader:
196 ; CHECK: br label %while.body
197 define void @test7(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
199 %brmerge.demorgan = and i1 %t1, %t2
200 br i1 %brmerge.demorgan, label %while.preheader, label %if.end
202 while.preheader: ; preds = %entry
203 %cmp = icmp eq i32 %N, 0
204 br i1 %cmp, label %if.end, label %while.body
206 while.body: ; preds = %while.body, %while.preheader
207 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
208 %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
209 %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
210 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
211 %tmp = load i32, i32* %b.addr.07, align 4
212 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
213 store i32 %tmp, i32* %a.addr.08, align 4
214 %inc = add nuw i32 %i.09, 1
215 %exitcond = icmp eq i32 %inc, %N
216 br i1 %exitcond, label %if.end, label %while.body
218 if.end: ; preds = %while.body, %while.preheader, %entry
222 ; TODO: Can we rearrange the conditional blocks so that we can use the test form?
225 ; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 %N, 0
226 ; CHECK: br i1 [[CMP]], label %while.preheader
227 ; CHECK: while.preheader:
228 ; CHECK: br i1 %brmerge.demorgan, label %while.body.preheader
229 ; CHECK: while.body.preheader:
230 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N)
231 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N)
232 ; CHECK: br label %while.body
233 define void @test8(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
235 %cmp = icmp ne i32 %N, 0
236 br i1 %cmp, label %while.preheader, label %if.end
238 while.preheader: ; preds = %entry
239 %brmerge.demorgan = and i1 %t1, %t2
240 br i1 %brmerge.demorgan, label %while.body, label %if.end
242 while.body: ; preds = %while.body, %while.preheader
243 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
244 %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
245 %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
246 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
247 %tmp = load i32, i32* %b.addr.07, align 4
248 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
249 store i32 %tmp, i32* %a.addr.08, align 4
250 %inc = add nuw i32 %i.09, 1
251 %exitcond = icmp eq i32 %inc, %N
252 br i1 %exitcond, label %if.end, label %while.body
254 if.end: ; preds = %while.body, %while.preheader, %entry
260 ; CHECK: br i1 %brmerge.demorgan, label %do.body.preheader
261 ; CHECK: do.body.preheader:
262 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N)
263 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N)
264 ; CHECK: br label %do.body
265 define void @test9(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
267 %cmp = icmp ne i32 %N, 0
268 %brmerge.demorgan = and i1 %t1, %cmp
269 br i1 %brmerge.demorgan, label %do.body, label %if.end
271 do.body: ; preds = %do.body, %entry
272 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
273 %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
274 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
275 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
276 %tmp = load i32, i32* %b.addr.0, align 4
277 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
278 store i32 %tmp, i32* %a.addr.0, align 4
279 %inc = add nuw i32 %i.0, 1
280 %cmp.1 = icmp ult i32 %inc, %N
281 br i1 %cmp.1, label %do.body, label %if.end
283 if.end: ; preds = %do.body, %entry
287 ; CHECK-LABEL: test10
289 ; CHECK: br i1 %cmp.1, label %do.body.preheader
290 ; CHECK: do.body.preheader:
291 ; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32
292 ; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32
293 ; CHECK: br label %do.body
294 define void @test10(i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
296 %cmp = icmp ne i32 %N, 0
298 %be = select i1 %cmp, i32 0, i32 %sub
299 %cmp.1 = icmp ne i32 %be, 0
300 br i1 %cmp.1, label %do.body, label %if.end
302 do.body: ; preds = %do.body, %entry
303 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
304 %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
305 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
306 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
307 %tmp = load i32, i32* %b.addr.0, align 4
308 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
309 store i32 %tmp, i32* %a.addr.0, align 4
310 %inc = add nuw i32 %i.0, 1
311 %cmp.2 = icmp ult i32 %inc, %N
312 br i1 %cmp.2, label %do.body, label %if.end
314 if.end: ; preds = %do.body, %entry
318 ; CHECK-LABEL: test11
320 ; CHECK: br label %do.body.preheader
321 ; CHECK: do.body.preheader:
322 ; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
323 ; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N)
324 ; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1
325 ; CHECK: br i1 [[TEST]], label %do.body.preheader1, label %if.end
326 ; CHECK: do.body.preheader1:
327 ; CHECK: br label %do.body
328 define void @test11(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
330 br label %do.body.preheader
333 %cmp = icmp ne i32 %N, 0
334 br i1 %cmp, label %do.body, label %if.end
337 %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %do.body.preheader ]
338 %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %do.body.preheader ]
339 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %do.body.preheader ]
340 %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
341 %tmp = load i32, i32* %b.addr.0, align 4
342 %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
343 store i32 %tmp, i32* %a.addr.0, align 4
344 %inc = add nuw i32 %i.0, 1
345 %cmp.1 = icmp ult i32 %inc, %N
346 br i1 %cmp.1, label %do.body, label %if.end
348 if.end: ; preds = %do.body, %entry
352 ; CHECK-LABEL: test12
354 ; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %conv)
355 ; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %conv)
356 ; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1
357 ; CHECK: br i1 [[TEST]], label %for.body.preheader, label %for.end
358 ; CHECK: for.body.preheader:
359 ; CHECK: br label %for.body
361 define void @test12(i32* nocapture %a, i32* nocapture readonly %b, i16 zeroext %length) {
363 %conv = zext i16 %length to i32
364 %cmp8.not = icmp eq i16 %length, 0
365 br i1 %cmp8.not, label %for.end, label %for.body
367 for.body: ; preds = %entry, %for.body
368 %i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
369 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.09
370 %0 = load i32, i32* %arrayidx, align 4
371 %arrayidx2 = getelementptr inbounds i32, i32* %a, i32 %i.09
372 store i32 %0, i32* %arrayidx2, align 4
373 %inc = add nuw nsw i32 %i.09, 1
374 %exitcond.not = icmp eq i32 %inc, %conv
375 br i1 %exitcond.not, label %for.end, label %for.body
377 for.end: ; preds = %for.body, %entry