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
4
5; NO-GUARD-NOT: @llvm.test.set.loop.iterations
6
7; CHECK-LABEL: test1
8; CHECK: entry:
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
16define void @test1(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
17entry:
18  br i1 %t1, label %do.body, label %if.end
19
20do.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
31
32if.end:                                           ; preds = %do.body, %entry
33  ret void
34}
35
36; CHECK-LABEL: test2
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
40define void @test2(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
41entry:
42  br i1 %t1, label %do.body, label %if.end
43
44do.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
55
56if.end:                                           ; preds = %do.body, %entry
57  ret void
58}
59
60; CHECK-LABEL: test3
61; CHECK: 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
68define void @test3(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
69entry:
70  %brmerge.demorgan = and i1 %t1, %t2
71  br i1 %brmerge.demorgan, label %do.body, label %if.end
72
73do.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
84
85if.end:                                           ; preds = %do.body, %entry
86  ret void
87}
88
89; CHECK-LABEL: test4
90; CHECK: 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
98define void @test4(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
99entry:
100  %brmerge.demorgan = and i1 %t1, %t2
101  br i1 %brmerge.demorgan, label %while.cond, label %if.end
102
103while.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
109
110while.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
116  br label %while.cond
117
118if.end:                                           ; preds = %while.cond, %entry
119  ret void
120}
121
122; CHECK-LABEL: test5
123; CHECK: 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
129define void @test5(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
130entry:
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
135
136while.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
147
148if.end:                                           ; preds = %while.body, %entry
149  ret void
150}
151
152; CHECK-LABEL: test6
153; CHECK: entry:
154; CHECK:   br i1 %brmerge.demorgan, label %while.preheader
155; CHECK: while.preheader:
156; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
157; CHECK:   br i1 [[TEST]], label %while.body.preheader, label %if.end
158; CHECK: while.body.preheader:
159; CHECK:   br label %while.body
160define void @test6(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
161entry:
162  %brmerge.demorgan = and i1 %t1, %t2
163  br i1 %brmerge.demorgan, label %while.preheader, label %if.end
164
165while.preheader:                                  ; preds = %entry
166  %cmp = icmp ne i32 %N, 0
167  br i1 %cmp, label %while.body, label %if.end
168
169while.body:                                       ; preds = %while.body, %while.preheader
170  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
171  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
172  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
173  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
174  %tmp = load i32, i32* %b.addr.07, align 4
175  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
176  store i32 %tmp, i32* %a.addr.08, align 4
177  %inc = add nuw i32 %i.09, 1
178  %exitcond = icmp eq i32 %inc, %N
179  br i1 %exitcond, label %if.end, label %while.body
180
181if.end:                                           ; preds = %while.body, %while.preheader, %entry
182  ret void
183}
184
185; CHECK-LABEL: test7
186; CHECK: entry:
187; CHECK:   br i1 %brmerge.demorgan, label %while.preheader
188; CHECK: while.preheader:
189; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
190; CHECK:   br i1 [[TEST]], label %while.body.preheader, label %if.end
191; CHECK: while.body.preheader:
192; CHECK:   br label %while.body
193define void @test7(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
194entry:
195  %brmerge.demorgan = and i1 %t1, %t2
196  br i1 %brmerge.demorgan, label %while.preheader, label %if.end
197
198while.preheader:                                  ; preds = %entry
199  %cmp = icmp eq i32 %N, 0
200  br i1 %cmp, label %if.end, label %while.body
201
202while.body:                                       ; preds = %while.body, %while.preheader
203  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
204  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
205  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
206  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
207  %tmp = load i32, i32* %b.addr.07, align 4
208  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
209  store i32 %tmp, i32* %a.addr.08, align 4
210  %inc = add nuw i32 %i.09, 1
211  %exitcond = icmp eq i32 %inc, %N
212  br i1 %exitcond, label %if.end, label %while.body
213
214if.end:                                           ; preds = %while.body, %while.preheader, %entry
215  ret void
216}
217
218; TODO: Can we rearrange the conditional blocks so that we can use the test form?
219; CHECK-LABEL: test8
220; CHECK: entry:
221; CHECK:   [[CMP:%[^ ]+]] = icmp ne i32 %N, 0
222; CHECK:   br i1 [[CMP]], label %while.preheader
223; CHECK: while.preheader:
224; CHECK:   br i1 %brmerge.demorgan, label %while.body.preheader
225; CHECK: while.body.preheader:
226; CHECK-EXIT:   call void @llvm.set.loop.iterations.i32(i32 %N)
227; CHECK-LATCH:   call i32 @llvm.start.loop.iterations.i32(i32 %N)
228; CHECK:   br label %while.body
229define void @test8(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
230entry:
231  %cmp = icmp ne i32 %N, 0
232  br i1 %cmp, label %while.preheader, label %if.end
233
234while.preheader:                                  ; preds = %entry
235  %brmerge.demorgan = and i1 %t1, %t2
236  br i1 %brmerge.demorgan, label %while.body, label %if.end
237
238while.body:                                       ; preds = %while.body, %while.preheader
239  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
240  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
241  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
242  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
243  %tmp = load i32, i32* %b.addr.07, align 4
244  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
245  store i32 %tmp, i32* %a.addr.08, align 4
246  %inc = add nuw i32 %i.09, 1
247  %exitcond = icmp eq i32 %inc, %N
248  br i1 %exitcond, label %if.end, label %while.body
249
250if.end:                                           ; preds = %while.body, %while.preheader, %entry
251  ret void
252}
253
254; CHECK-LABEL: test9
255; CHECK: entry:
256; CHECK:   br i1 %brmerge.demorgan, label %do.body.preheader
257; CHECK: do.body.preheader:
258; CHECK-EXIT:   call void @llvm.set.loop.iterations.i32(i32 %N)
259; CHECK-LATCH:   call i32 @llvm.start.loop.iterations.i32(i32 %N)
260; CHECK:   br label %do.body
261define void @test9(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
262entry:
263  %cmp = icmp ne i32 %N, 0
264  %brmerge.demorgan = and i1 %t1, %cmp
265  br i1 %brmerge.demorgan, label %do.body, label %if.end
266
267do.body:                                          ; preds = %do.body, %entry
268  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
269  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
270  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
271  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
272  %tmp = load i32, i32* %b.addr.0, align 4
273  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
274  store i32 %tmp, i32* %a.addr.0, align 4
275  %inc = add nuw i32 %i.0, 1
276  %cmp.1 = icmp ult i32 %inc, %N
277  br i1 %cmp.1, label %do.body, label %if.end
278
279if.end:                                           ; preds = %do.body, %entry
280  ret void
281}
282
283; CHECK-LABEL: test10
284; CHECK: entry:
285; CHECK:   br i1 %cmp.1, label %do.body.preheader
286; CHECK: do.body.preheader:
287; CHECK-EXIT:   call void @llvm.set.loop.iterations.i32(i32
288; CHECK-LATCH:   call i32 @llvm.start.loop.iterations.i32(i32
289; CHECK:   br label %do.body
290define void @test10(i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
291entry:
292  %cmp = icmp ne i32 %N, 0
293  %sub = sub i32 %N, 1
294  %be = select i1 %cmp, i32 0, i32 %sub
295  %cmp.1 = icmp ne i32 %be, 0
296  br i1 %cmp.1, label %do.body, label %if.end
297
298do.body:                                          ; preds = %do.body, %entry
299  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
300  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
301  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
302  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
303  %tmp = load i32, i32* %b.addr.0, align 4
304  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
305  store i32 %tmp, i32* %a.addr.0, align 4
306  %inc = add nuw i32 %i.0, 1
307  %cmp.2 = icmp ult i32 %inc, %N
308  br i1 %cmp.2, label %do.body, label %if.end
309
310if.end:                                           ; preds = %do.body, %entry
311  ret void
312}
313
314; CHECK-LABEL: test11
315; CHECK: entry:
316; CHECK:   br label %do.body.preheader
317; CHECK: do.body.preheader:
318; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
319; CHECK:   br i1 [[TEST]], label %do.body.preheader1, label %if.end
320; CHECK: do.body.preheader1:
321; CHECK:   br label %do.body
322define void @test11(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
323entry:
324  br label %do.body.preheader
325
326do.body.preheader:
327  %cmp = icmp ne i32 %N, 0
328  br i1 %cmp, label %do.body, label %if.end
329
330do.body:
331  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %do.body.preheader ]
332  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %do.body.preheader ]
333  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %do.body.preheader ]
334  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
335  %tmp = load i32, i32* %b.addr.0, align 4
336  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
337  store i32 %tmp, i32* %a.addr.0, align 4
338  %inc = add nuw i32 %i.0, 1
339  %cmp.1 = icmp ult i32 %inc, %N
340  br i1 %cmp.1, label %do.body, label %if.end
341
342if.end:                                           ; preds = %do.body, %entry
343  ret void
344}
345