[RISCV] Use RISCVSubtarget::is64Bit() instead of hasFeature(RISCV::Feature64Bit)...
[llvm-project.git] / llvm / test / Transforms / HardwareLoops / loop-guards.ll
blob43aae5ea35b4d90bf0833659059b2925c9b2b237
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
5 ; NO-GUARD-NOT: @llvm.test.set.loop.iterations
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
16 define void @test1(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
17 entry:
18   br i1 %t1, label %do.body, label %if.end
20 do.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
32 if.end:                                           ; preds = %do.body, %entry
33   ret void
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
40 define void @test2(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
41 entry:
42   br i1 %t1, label %do.body, label %if.end
44 do.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
56 if.end:                                           ; preds = %do.body, %entry
57   ret void
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
68 define void @test3(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
69 entry:
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 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
85 if.end:                                           ; preds = %do.body, %entry
86   ret void
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
98 define void @test4(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
99 entry:
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 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
110 while.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
118 if.end:                                           ; preds = %while.cond, %entry
119   ret void
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
129 define void @test5(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
130 entry:
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 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
148 if.end:                                           ; preds = %while.body, %entry
149   ret void
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
162 define void @test6(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
163 entry:
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 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
183 if.end:                                           ; preds = %while.body, %while.preheader, %entry
184   ret void
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
197 define void @test7(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
198 entry:
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 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
218 if.end:                                           ; preds = %while.body, %while.preheader, %entry
219   ret void
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
233 define void @test8(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
234 entry:
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 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
254 if.end:                                           ; preds = %while.body, %while.preheader, %entry
255   ret void
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
265 define void @test9(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
266 entry:
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 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
283 if.end:                                           ; preds = %do.body, %entry
284   ret void
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
294 define void @test10(ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
295 entry:
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
302 do.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
314 if.end:                                           ; preds = %do.body, %entry
315   ret void
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
328 define void @test11(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) {
329 entry:
330   br label %do.body.preheader
332 do.body.preheader:
333   %cmp = icmp ne i32 %N, 0
334   br i1 %cmp, label %do.body, label %if.end
336 do.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
348 if.end:                                           ; preds = %do.body, %entry
349   ret void
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
361 define void @test12(ptr nocapture %a, ptr nocapture readonly %b, i16 zeroext %length) {
362 entry:
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, 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
377 for.end:                                          ; preds = %for.body, %entry
378   ret void