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