Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopStrengthReduce / RISCV / icmp-zero.ll
bloba8446c5103176e9ac0280341c1c49e4a29274faf
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -loop-reduce -S | FileCheck %s
4 target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
5 target triple = "riscv64"
8 define void @icmp_zero(i64 %N, ptr %p) {
9 ; CHECK-LABEL: @icmp_zero(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
12 ; CHECK:       vector.body:
13 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
14 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
15 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
16 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
17 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
18 ; CHECK:       exit:
19 ; CHECK-NEXT:    ret void
21 entry:
22   br label %vector.body
24 vector.body:
25   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
26   store i64 0, ptr %p
27   %iv.next = add i64 %iv, 2
28   %done = icmp eq i64 %iv.next, %N
29   br i1 %done, label %exit, label %vector.body
31 exit:
32   ret void
35 define void @icmp_zero_urem_nonzero_con(i64 %N, ptr %p) {
36 ; CHECK-LABEL: @icmp_zero_urem_nonzero_con(
37 ; CHECK-NEXT:  entry:
38 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], 16
39 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
40 ; CHECK:       vector.body:
41 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
42 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
43 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
44 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
45 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
46 ; CHECK:       exit:
47 ; CHECK-NEXT:    ret void
49 entry:
50   %urem = urem i64 %N, 16
51   br label %vector.body
53 vector.body:
54   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
55   store i64 0, ptr %p
56   %iv.next = add i64 %iv, 2
57   %done = icmp eq i64 %iv.next, %urem
58   br i1 %done, label %exit, label %vector.body
60 exit:
61   ret void
64 define void @icmp_zero_urem_invariant(i64 %N, i64 %M, ptr %p) {
65 ; CHECK-LABEL: @icmp_zero_urem_invariant(
66 ; CHECK-NEXT:  entry:
67 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]
68 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
69 ; CHECK:       vector.body:
70 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
71 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
72 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
73 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
74 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
75 ; CHECK:       exit:
76 ; CHECK-NEXT:    ret void
78 entry:
79   %urem = urem i64 %N, %M
80   br label %vector.body
82 vector.body:
83   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
84   store i64 0, ptr %p
85   %iv.next = add i64 %iv, 2
86   %done = icmp eq i64 %iv.next, %urem
87   br i1 %done, label %exit, label %vector.body
89 exit:
90   ret void
93 ; We have to be careful here as SCEV can only compute a subtraction from
94 ; two pointers with the same base.  If we hide %end inside a unknown, we
95 ; can no longer compute the subtract.
96 define void @icmp_zero_urem_invariant_ptr(i64 %N, i64 %M, ptr %p) {
97 ; CHECK-LABEL: @icmp_zero_urem_invariant_ptr(
98 ; CHECK-NEXT:  entry:
99 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]
100 ; CHECK-NEXT:    [[END:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[UREM]]
101 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
102 ; CHECK:       vector.body:
103 ; CHECK-NEXT:    [[IV:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
104 ; CHECK-NEXT:    store i64 0, ptr [[P]], align 8
105 ; CHECK-NEXT:    [[IV_NEXT]] = getelementptr i64, ptr [[IV]], i64 1
106 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq ptr [[IV_NEXT]], [[END]]
107 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
108 ; CHECK:       exit:
109 ; CHECK-NEXT:    ret void
111 entry:
112   %urem = urem i64 %N, %M
113   %end = getelementptr i64, ptr %p, i64 %urem
114   br label %vector.body
116 vector.body:
117   %iv = phi ptr [ %p, %entry ], [ %iv.next, %vector.body ]
118   store i64 0, ptr %p
119   %iv.next = getelementptr i64, ptr %iv, i64 1
120   %done = icmp eq ptr %iv.next, %end
121   br i1 %done, label %exit, label %vector.body
123 exit:
124   ret void
127 ; Negative test - We can not hoist because we don't know value of %M.
128 define void @icmp_zero_urem_nohoist(i64 %N, i64 %M, ptr %p) {
129 ; CHECK-LABEL: @icmp_zero_urem_nohoist(
130 ; CHECK-NEXT:  entry:
131 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
132 ; CHECK:       vector.body:
133 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
134 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
135 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 2
136 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]
137 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]
138 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
139 ; CHECK:       exit:
140 ; CHECK-NEXT:    ret void
142 entry:
143   br label %vector.body
145 vector.body:
146   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
147   store i64 0, ptr %p
148   %iv.next = add i64 %iv, 2
149   %urem = urem i64 %N, %M
150   %done = icmp eq i64 %iv.next, %urem
151   br i1 %done, label %exit, label %vector.body
153 exit:
154   ret void
157 define void @icmp_zero_urem_nonzero(i64 %N, i64 %M, ptr %p) {
158 ; CHECK-LABEL: @icmp_zero_urem_nonzero(
159 ; CHECK-NEXT:  entry:
160 ; CHECK-NEXT:    [[NONZERO:%.*]] = add nuw i64 [[M:%.*]], 1
161 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[NONZERO]]
162 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
163 ; CHECK:       vector.body:
164 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
165 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
166 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
167 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
168 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
169 ; CHECK:       exit:
170 ; CHECK-NEXT:    ret void
172 entry:
173   %nonzero = add nuw i64 %M, 1
174   %urem = urem i64 %N, %nonzero
175   br label %vector.body
177 vector.body:
178   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
179   store i64 0, ptr %p
180   %iv.next = add i64 %iv, 2
181   %done = icmp eq i64 %iv.next, %urem
182   br i1 %done, label %exit, label %vector.body
184 exit:
185   ret void
188 define void @icmp_zero_urem_vscale(i64 %N, ptr %p) {
189 ; CHECK-LABEL: @icmp_zero_urem_vscale(
190 ; CHECK-NEXT:  entry:
191 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
192 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[VSCALE]]
193 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
194 ; CHECK:       vector.body:
195 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
196 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
197 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
198 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
199 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
200 ; CHECK:       exit:
201 ; CHECK-NEXT:    ret void
203 entry:
204   %vscale = call i64 @llvm.vscale.i64()
205   %urem = urem i64 %N, %vscale
206   br label %vector.body
208 vector.body:
209   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
210   store i64 0, ptr %p
211   %iv.next = add i64 %iv, 2
212   %done = icmp eq i64 %iv.next, %urem
213   br i1 %done, label %exit, label %vector.body
215 exit:
216   ret void
219 define void @icmp_zero_urem_vscale_mul8(i64 %N, ptr %p) {
220 ; CHECK-LABEL: @icmp_zero_urem_vscale_mul8(
221 ; CHECK-NEXT:  entry:
222 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
223 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 8
224 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[MUL]]
225 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
226 ; CHECK:       vector.body:
227 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
228 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
229 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
230 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
231 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
232 ; CHECK:       exit:
233 ; CHECK-NEXT:    ret void
235 entry:
236   %vscale = call i64 @llvm.vscale.i64()
237   %mul = mul nuw nsw i64 %vscale, 8
238   %urem = urem i64 %N, %mul
239   br label %vector.body
241 vector.body:
242   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
243   store i64 0, ptr %p
244   %iv.next = add i64 %iv, 2
245   %done = icmp eq i64 %iv.next, %urem
246   br i1 %done, label %exit, label %vector.body
248 exit:
249   ret void
253 define void @icmp_zero_urem_vscale_mul64(i64 %N, ptr %p) {
254 ; CHECK-LABEL: @icmp_zero_urem_vscale_mul64(
255 ; CHECK-NEXT:  entry:
256 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
257 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 64
258 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[MUL]]
259 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
260 ; CHECK:       vector.body:
261 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
262 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
263 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
264 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
265 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
266 ; CHECK:       exit:
267 ; CHECK-NEXT:    ret void
269 entry:
270   %vscale = call i64 @llvm.vscale.i64()
271   %mul = mul nuw nsw i64 %vscale, 64
272   %urem = urem i64 %N, %mul
273   br label %vector.body
275 vector.body:
276   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
277   store i64 0, ptr %p
278   %iv.next = add i64 %iv, 2
279   %done = icmp eq i64 %iv.next, %urem
280   br i1 %done, label %exit, label %vector.body
282 exit:
283   ret void
286 define void @icmp_zero_urem_vscale_shl3(i64 %N, ptr %p) {
287 ; CHECK-LABEL: @icmp_zero_urem_vscale_shl3(
288 ; CHECK-NEXT:  entry:
289 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
290 ; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VSCALE]], 3
291 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]]
292 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
293 ; CHECK:       vector.body:
294 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
295 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
296 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
297 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
298 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
299 ; CHECK:       exit:
300 ; CHECK-NEXT:    ret void
302 entry:
303   %vscale = call i64 @llvm.vscale.i64()
304   %shl = shl i64 %vscale, 3
305   %urem = urem i64 %N, %shl
306   br label %vector.body
308 vector.body:
309   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
310   store i64 0, ptr %p
311   %iv.next = add i64 %iv, 2
312   %done = icmp eq i64 %iv.next, %urem
313   br i1 %done, label %exit, label %vector.body
315 exit:
316   ret void
319 define void @icmp_zero_urem_vscale_shl6(i64 %N, ptr %p) {
320 ; CHECK-LABEL: @icmp_zero_urem_vscale_shl6(
321 ; CHECK-NEXT:  entry:
322 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
323 ; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VSCALE]], 6
324 ; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]]
325 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
326 ; CHECK:       vector.body:
327 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
328 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 8
329 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
330 ; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
331 ; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
332 ; CHECK:       exit:
333 ; CHECK-NEXT:    ret void
335 entry:
336   %vscale = call i64 @llvm.vscale.i64()
337   %shl = shl i64 %vscale, 6
338   %urem = urem i64 %N, %shl
339   br label %vector.body
341 vector.body:
342   %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
343   store i64 0, ptr %p
344   %iv.next = add i64 %iv, 2
345   %done = icmp eq i64 %iv.next, %urem
346   br i1 %done, label %exit, label %vector.body
348 exit:
349   ret void
352 ; Loop invariant does not neccessarily mean dominating the loop.  Forming
353 ; an ICmpZero from this example would be illegal even though the operands
354 ; to the compare are loop invariant.
355 define void @loop_invariant_definition(i64 %arg) {
356 ; CHECK-LABEL: @loop_invariant_definition(
357 ; CHECK-NEXT:  entry:
358 ; CHECK-NEXT:    br label [[T1:%.*]]
359 ; CHECK:       t1:
360 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[T1]] ], [ -1, [[ENTRY:%.*]] ]
361 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], 1
362 ; CHECK-NEXT:    br i1 true, label [[T4:%.*]], label [[T1]]
363 ; CHECK:       t4:
364 ; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[LSR_IV_NEXT]] to i32
365 ; CHECK-NEXT:    [[T6:%.*]] = add i32 [[T5]], 1
366 ; CHECK-NEXT:    [[T7:%.*]] = icmp eq i32 [[T5]], [[T6]]
367 ; CHECK-NEXT:    ret void
369 entry:
370   br label %t1
372 t1:                                                ; preds = %1, %0
373   %t2 = phi i64 [ %t3, %t1 ], [ 0, %entry ]
374   %t3 = add nuw i64 %t2, 1
375   br i1 true, label %t4, label %t1
377 t4:                                                ; preds = %1
378   %t5 = trunc i64 %t2 to i32
379   %t6 = add i32 %t5, 1
380   %t7 = icmp eq i32 %t5, %t6
381   ret void
384 declare i64 @llvm.vscale.i64()