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:   [[CMP:%[^ ]+]] = icmp ugt i32 %N, 2
10; CHECK:   [[MAX:%[^ ]+]] = select i1 [[CMP]], i32 %N, i32 2
11; CHECK:   [[COUNT:%[^ ]+]] = add i32 [[MAX]], -1
12; CHECK:   br i1 %t1, label %do.body.preheader
13; CHECK: do.body.preheader:
14; CHECK:   call void @llvm.set.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
39define void @test2(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
40entry:
41  br i1 %t1, label %do.body, label %if.end
42
43do.body:                                          ; preds = %do.body, %entry
44  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
45  %a.addr.0 = phi i32* [ %incdec.ptr1, %do.body ], [ %a, %entry ]
46  %i.0 = phi i32 [ %add, %do.body ], [ 1, %entry ]
47  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
48  %tmp = load i32, i32* %b.addr.0, align 4
49  %incdec.ptr1 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
50  store i32 %tmp, i32* %a.addr.0, align 4
51  %add = add i32 %i.0, 2
52  %cmp = icmp ult i32 %add, %N
53  br i1 %cmp, label %do.body, label %if.end
54
55if.end:                                           ; preds = %do.body, %entry
56  ret void
57}
58
59; CHECK-LABEL: test3
60; CHECK: entry:
61; CHECK:   [[CMP:%[^ ]+]] = icmp ugt i32 %N, 1
62; CHECK:   [[COUNT:%[^ ]+]] = select i1 [[CMP]], i32 %N, i32 1
63; CHECK:   br i1 %brmerge.demorgan, label %do.body.preheader
64; CHECK: do.body.preheader:
65; CHECK:   call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
66; CHECK:   br label %do.body
67define void @test3(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
68entry:
69  %brmerge.demorgan = and i1 %t1, %t2
70  br i1 %brmerge.demorgan, label %do.body, label %if.end
71
72do.body:                                          ; preds = %do.body, %entry
73  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
74  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
75  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
76  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
77  %tmp = load i32, i32* %b.addr.0, align 4
78  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
79  store i32 %tmp, i32* %a.addr.0, align 4
80  %inc = add nuw i32 %i.0, 1
81  %cmp = icmp ult i32 %inc, %N
82  br i1 %cmp, label %do.body, label %if.end
83
84if.end:                                           ; preds = %do.body, %entry
85  ret void
86}
87
88; CHECK-LABEL: test4
89; CHECK: entry:
90; CHECK-LATCH:  br i1 %brmerge.demorgan, label %while.cond
91; CHECK-LATCH-NOT: call void @llvm{{.*}}loop.iterations
92; CHECK-EXIT:   br i1 %brmerge.demorgan, label %while.cond.preheader
93; CHECK-EXIT: while.cond.preheader:
94; CHECK-EXIT:   [[COUNT:%[^ ]+]] = add i32 %N, 1
95; CHECK-EXIT:   call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
96; CHECK-EXIT:   br label %while.cond
97define void @test4(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
98entry:
99  %brmerge.demorgan = and i1 %t1, %t2
100  br i1 %brmerge.demorgan, label %while.cond, label %if.end
101
102while.cond:                                       ; preds = %while.body, %entry
103  %b.addr.0 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %entry ]
104  %a.addr.0 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %entry ]
105  %i.0 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
106  %exitcond = icmp eq i32 %i.0, %N
107  br i1 %exitcond, label %if.end, label %while.body
108
109while.body:                                       ; preds = %while.cond
110  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
111  %tmp = load i32, i32* %b.addr.0, align 4
112  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
113  store i32 %tmp, i32* %a.addr.0, align 4
114  %inc = add i32 %i.0, 1
115  br label %while.cond
116
117if.end:                                           ; preds = %while.cond, %entry
118  ret void
119}
120
121; CHECK-LABEL: test5
122; CHECK: entry:
123; CHECK:   br i1 %or.cond, label %while.body.preheader
124; CHECK: while.body.preheader:
125; CHECK:   call void @llvm.set.loop.iterations.i32(i32 %N)
126; CHECK:   br label %while.body
127define void @test5(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
128entry:
129  %brmerge.demorgan = and i1 %t1, %t2
130  %cmp6 = icmp ne i32 %N, 0
131  %or.cond = and i1 %brmerge.demorgan, %cmp6
132  br i1 %or.cond, label %while.body, label %if.end
133
134while.body:                                       ; preds = %while.body, %entry
135  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
136  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %entry ]
137  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %entry ]
138  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
139  %tmp = load i32, i32* %b.addr.07, align 4
140  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
141  store i32 %tmp, i32* %a.addr.08, align 4
142  %inc = add nuw i32 %i.09, 1
143  %exitcond = icmp eq i32 %inc, %N
144  br i1 %exitcond, label %if.end, label %while.body
145
146if.end:                                           ; preds = %while.body, %entry
147  ret void
148}
149
150; CHECK-LABEL: test6
151; CHECK: entry:
152; CHECK:   br i1 %brmerge.demorgan, label %while.preheader
153; CHECK: while.preheader:
154; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
155; CHECK:   br i1 [[TEST]], label %while.body.preheader, label %if.end
156; CHECK: while.body.preheader:
157; CHECK:   br label %while.body
158define void @test6(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
159entry:
160  %brmerge.demorgan = and i1 %t1, %t2
161  br i1 %brmerge.demorgan, label %while.preheader, label %if.end
162
163while.preheader:                                  ; preds = %entry
164  %cmp = icmp ne i32 %N, 0
165  br i1 %cmp, label %while.body, label %if.end
166
167while.body:                                       ; preds = %while.body, %while.preheader
168  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
169  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
170  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
171  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
172  %tmp = load i32, i32* %b.addr.07, align 4
173  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
174  store i32 %tmp, i32* %a.addr.08, align 4
175  %inc = add nuw i32 %i.09, 1
176  %exitcond = icmp eq i32 %inc, %N
177  br i1 %exitcond, label %if.end, label %while.body
178
179if.end:                                           ; preds = %while.body, %while.preheader, %entry
180  ret void
181}
182
183; CHECK-LABEL: test7
184; CHECK: entry:
185; CHECK:   br i1 %brmerge.demorgan, label %while.preheader
186; CHECK: while.preheader:
187; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
188; CHECK:   br i1 [[TEST]], label %while.body.preheader, label %if.end
189; CHECK: while.body.preheader:
190; CHECK:   br label %while.body
191define void @test7(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
192entry:
193  %brmerge.demorgan = and i1 %t1, %t2
194  br i1 %brmerge.demorgan, label %while.preheader, label %if.end
195
196while.preheader:                                  ; preds = %entry
197  %cmp = icmp eq i32 %N, 0
198  br i1 %cmp, label %if.end, label %while.body
199
200while.body:                                       ; preds = %while.body, %while.preheader
201  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
202  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
203  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
204  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
205  %tmp = load i32, i32* %b.addr.07, align 4
206  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
207  store i32 %tmp, i32* %a.addr.08, align 4
208  %inc = add nuw i32 %i.09, 1
209  %exitcond = icmp eq i32 %inc, %N
210  br i1 %exitcond, label %if.end, label %while.body
211
212if.end:                                           ; preds = %while.body, %while.preheader, %entry
213  ret void
214}
215
216; TODO: Can we rearrange the conditional blocks so that we can use the test form?
217; CHECK-LABEL: test8
218; CHECK: entry:
219; CHECK:   [[CMP:%[^ ]+]] = icmp ne i32 %N, 0
220; CHECK:   br i1 [[CMP]], label %while.preheader
221; CHECK: while.preheader:
222; CHECK:   br i1 %brmerge.demorgan, label %while.body.preheader
223; CHECK: while.body.preheader:
224; CHECK:   call void @llvm.set.loop.iterations.i32(i32 %N)
225; CHECK:   br label %while.body
226define void @test8(i1 zeroext %t1, i1 zeroext %t2, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
227entry:
228  %cmp = icmp ne i32 %N, 0
229  br i1 %cmp, label %while.preheader, label %if.end
230
231while.preheader:                                  ; preds = %entry
232  %brmerge.demorgan = and i1 %t1, %t2
233  br i1 %brmerge.demorgan, label %while.body, label %if.end
234
235while.body:                                       ; preds = %while.body, %while.preheader
236  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
237  %a.addr.08 = phi i32* [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
238  %b.addr.07 = phi i32* [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
239  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.07, i32 1
240  %tmp = load i32, i32* %b.addr.07, align 4
241  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.08, i32 1
242  store i32 %tmp, i32* %a.addr.08, align 4
243  %inc = add nuw i32 %i.09, 1
244  %exitcond = icmp eq i32 %inc, %N
245  br i1 %exitcond, label %if.end, label %while.body
246
247if.end:                                           ; preds = %while.body, %while.preheader, %entry
248  ret void
249}
250
251; CHECK-LABEL: test9
252; CHECK: entry:
253; CHECK:   br i1 %brmerge.demorgan, label %do.body.preheader
254; CHECK: do.body.preheader:
255; CHECK:   call void @llvm.set.loop.iterations.i32(i32 %N)
256; CHECK:   br label %do.body
257define void @test9(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
258entry:
259  %cmp = icmp ne i32 %N, 0
260  %brmerge.demorgan = and i1 %t1, %cmp
261  br i1 %brmerge.demorgan, label %do.body, label %if.end
262
263do.body:                                          ; preds = %do.body, %entry
264  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
265  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
266  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
267  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
268  %tmp = load i32, i32* %b.addr.0, align 4
269  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
270  store i32 %tmp, i32* %a.addr.0, align 4
271  %inc = add nuw i32 %i.0, 1
272  %cmp.1 = icmp ult i32 %inc, %N
273  br i1 %cmp.1, label %do.body, label %if.end
274
275if.end:                                           ; preds = %do.body, %entry
276  ret void
277}
278
279; CHECK-LABEL: test10
280; CHECK: entry:
281; CHECK:   br i1 %cmp.1, label %do.body.preheader
282; CHECK: do.body.preheader:
283; CHECK:   call void @llvm.set.loop.iterations.i32(i32
284; CHECK:   br label %do.body
285define void @test10(i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
286entry:
287  %cmp = icmp ne i32 %N, 0
288  %sub = sub i32 %N, 1
289  %be = select i1 %cmp, i32 0, i32 %sub
290  %cmp.1 = icmp ne i32 %be, 0
291  br i1 %cmp.1, label %do.body, label %if.end
292
293do.body:                                          ; preds = %do.body, %entry
294  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %entry ]
295  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %entry ]
296  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
297  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
298  %tmp = load i32, i32* %b.addr.0, align 4
299  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
300  store i32 %tmp, i32* %a.addr.0, align 4
301  %inc = add nuw i32 %i.0, 1
302  %cmp.2 = icmp ult i32 %inc, %N
303  br i1 %cmp.2, label %do.body, label %if.end
304
305if.end:                                           ; preds = %do.body, %entry
306  ret void
307}
308
309; CHECK-LABEL: test11
310; CHECK: entry:
311; CHECK:   br label %do.body.preheader
312; CHECK: do.body.preheader:
313; CHECK:   [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
314; CHECK:   br i1 [[TEST]], label %do.body.preheader1, label %if.end
315; CHECK: do.body.preheader1:
316; CHECK:   br label %do.body
317define void @test11(i1 zeroext %t1, i32* nocapture %a, i32* nocapture readonly %b, i32 %N) {
318entry:
319  br label %do.body.preheader
320
321do.body.preheader:
322  %cmp = icmp ne i32 %N, 0
323  br i1 %cmp, label %do.body, label %if.end
324
325do.body:
326  %b.addr.0 = phi i32* [ %incdec.ptr, %do.body ], [ %b, %do.body.preheader ]
327  %a.addr.0 = phi i32* [ %incdec.ptr3, %do.body ], [ %a, %do.body.preheader ]
328  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %do.body.preheader ]
329  %incdec.ptr = getelementptr inbounds i32, i32* %b.addr.0, i32 1
330  %tmp = load i32, i32* %b.addr.0, align 4
331  %incdec.ptr3 = getelementptr inbounds i32, i32* %a.addr.0, i32 1
332  store i32 %tmp, i32* %a.addr.0, align 4
333  %inc = add nuw i32 %i.0, 1
334  %cmp.1 = icmp ult i32 %inc, %N
335  br i1 %cmp.1, label %do.body, label %if.end
336
337if.end:                                           ; preds = %do.body, %entry
338  ret void
339}
340