xref: /llvm-project/llvm/test/Transforms/HardwareLoops/loop-guards.ll (revision 2a58be42396376e8d552158ff801d953c6c1bee3)
1; RUN: opt -passes='hardware-loops<force-hardware-loops;force-hardware-loop-guard;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EXIT
2; RUN: opt -passes='hardware-loops<force-hardware-loops;force-hardware-loop-guard;force-hardware-loop-phi;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LATCH
3; RUN: opt -passes='hardware-loops<force-hardware-loops;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -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, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr, %do.body ], [ %b, %entry ]
22  %a.addr.0 = phi ptr [ %incdec.ptr1, %do.body ], [ %a, %entry ]
23  %i.0 = phi i32 [ %inc, %do.body ], [ 1, %entry ]
24  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1
25  %tmp = load i32, ptr %b.addr.0, align 4
26  %incdec.ptr1 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
27  store i32 %tmp, ptr %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, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr, %do.body ], [ %b, %entry ]
46  %a.addr.0 = phi ptr [ %incdec.ptr1, %do.body ], [ %a, %entry ]
47  %i.0 = phi i32 [ %add, %do.body ], [ 1, %entry ]
48  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1
49  %tmp = load i32, ptr %b.addr.0, align 4
50  %incdec.ptr1 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
51  store i32 %tmp, ptr %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, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr, %do.body ], [ %b, %entry ]
75  %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ]
76  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
77  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1
78  %tmp = load i32, ptr %b.addr.0, align 4
79  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
80  store i32 %tmp, ptr %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, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr, %while.body ], [ %b, %entry ]
105  %a.addr.0 = phi ptr [ %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, ptr %b.addr.0, i32 1
112  %tmp = load i32, ptr %b.addr.0, align 4
113  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
114  store i32 %tmp, ptr %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, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr3, %while.body ], [ %a, %entry ]
139  %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %entry ]
140  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1
141  %tmp = load i32, ptr %b.addr.07, align 4
142  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1
143  store i32 %tmp, ptr %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-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
162define void @test6(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr 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 ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
174  %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
175  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1
176  %tmp = load i32, ptr %b.addr.07, align 4
177  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1
178  store i32 %tmp, ptr %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-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
197define void @test7(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
198entry:
199  %brmerge.demorgan = and i1 %t1, %t2
200  br i1 %brmerge.demorgan, label %while.preheader, label %if.end
201
202while.preheader:                                  ; preds = %entry
203  %cmp = icmp eq i32 %N, 0
204  br i1 %cmp, label %if.end, label %while.body
205
206while.body:                                       ; preds = %while.body, %while.preheader
207  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
208  %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
209  %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
210  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1
211  %tmp = load i32, ptr %b.addr.07, align 4
212  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1
213  store i32 %tmp, ptr %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
217
218if.end:                                           ; preds = %while.body, %while.preheader, %entry
219  ret void
220}
221
222; TODO: Can we rearrange the conditional blocks so that we can use the test form?
223; CHECK-LABEL: test8
224; CHECK: entry:
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
233define void @test8(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
234entry:
235  %cmp = icmp ne i32 %N, 0
236  br i1 %cmp, label %while.preheader, label %if.end
237
238while.preheader:                                  ; preds = %entry
239  %brmerge.demorgan = and i1 %t1, %t2
240  br i1 %brmerge.demorgan, label %while.body, label %if.end
241
242while.body:                                       ; preds = %while.body, %while.preheader
243  %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ]
244  %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ]
245  %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ]
246  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1
247  %tmp = load i32, ptr %b.addr.07, align 4
248  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1
249  store i32 %tmp, ptr %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
253
254if.end:                                           ; preds = %while.body, %while.preheader, %entry
255  ret void
256}
257
258; CHECK-LABEL: test9
259; CHECK: 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
265define void @test9(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
266entry:
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
270
271do.body:                                          ; preds = %do.body, %entry
272  %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ]
273  %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ]
274  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
275  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1
276  %tmp = load i32, ptr %b.addr.0, align 4
277  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
278  store i32 %tmp, ptr %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
282
283if.end:                                           ; preds = %do.body, %entry
284  ret void
285}
286
287; CHECK-LABEL: test10
288; CHECK: entry:
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
294define void @test10(ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
295entry:
296  %cmp = icmp ne i32 %N, 0
297  %sub = sub i32 %N, 1
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
301
302do.body:                                          ; preds = %do.body, %entry
303  %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ]
304  %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ]
305  %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ]
306  %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1
307  %tmp = load i32, ptr %b.addr.0, align 4
308  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
309  store i32 %tmp, ptr %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
313
314if.end:                                           ; preds = %do.body, %entry
315  ret void
316}
317
318; CHECK-LABEL: test11
319; CHECK: entry:
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
328define void @test11(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
329entry:
330  br label %do.body.preheader
331
332do.body.preheader:
333  %cmp = icmp ne i32 %N, 0
334  br i1 %cmp, label %do.body, label %if.end
335
336do.body:
337  %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %do.body.preheader ]
338  %a.addr.0 = phi ptr [ %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, ptr %b.addr.0, i32 1
341  %tmp = load i32, ptr %b.addr.0, align 4
342  %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1
343  store i32 %tmp, ptr %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
347
348if.end:                                           ; preds = %do.body, %entry
349  ret void
350}
351
352; CHECK-LABEL: test12
353; CHECK: entry:
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
360
361define void @test12(ptr nocapture %a, ptr nocapture readonly %b, i16 zeroext %length) {
362entry:
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
366
367for.body:                                         ; preds = %entry, %for.body
368  %i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
369  %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.09
370  %0 = load i32, ptr %arrayidx, align 4
371  %arrayidx2 = getelementptr inbounds i32, ptr %a, i32 %i.09
372  store i32 %0, ptr %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
376
377for.end:                                          ; preds = %for.body, %entry
378  ret void
379}
380