Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / X86 / usub_inc_iv.ll
blob88bfddb51f2d492c1b04d68ed07f8df2768dbeba
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -mtriple=x86_64-linux -codegenprepare -S < %s | FileCheck %s
4 define i32 @test_01(ptr %p, i64 %len, i32 %x) {
5 ; CHECK-LABEL: @test_01(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    br label [[LOOP:%.*]]
8 ; CHECK:       loop:
9 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
10 ; CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)
11 ; CHECK-NEXT:    [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 0
12 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
13 ; CHECK-NEXT:    br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]
14 ; CHECK:       backedge:
15 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[MATH]], 4
16 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
17 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
18 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
19 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
20 ; CHECK:       exit:
21 ; CHECK-NEXT:    ret i32 -1
22 ; CHECK:       failure:
23 ; CHECK-NEXT:    unreachable
25 entry:
26   %scevgep = getelementptr i32, ptr %p, i64 -1
27   br label %loop
29 loop:                                             ; preds = %backedge, %entry
30   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
31   %iv.next = add i64 %iv, -1
32   %cond_1 = icmp eq i64 %iv, 0
33   br i1 %cond_1, label %exit, label %backedge
35 backedge:                                         ; preds = %loop
36   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
37   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
38   %cond_2 = icmp eq i32 %loaded, %x
39   br i1 %cond_2, label %failure, label %loop
41 exit:                                             ; preds = %loop
42   ret i32 -1
44 failure:                                          ; preds = %backedge
45   unreachable
48 ; Similar to test_01, but with different offset.
49 define i32 @test_01a(ptr %p, i64 %len, i32 %x) {
50 ; CHECK-LABEL: @test_01a(
51 ; CHECK-NEXT:  entry:
52 ; CHECK-NEXT:    br label [[LOOP:%.*]]
53 ; CHECK:       loop:
54 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
55 ; CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)
56 ; CHECK-NEXT:    [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 0
57 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
58 ; CHECK-NEXT:    br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]
59 ; CHECK:       backedge:
60 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[MATH]], 4
61 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
62 ; CHECK-NEXT:    [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -24
63 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4
64 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
65 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
66 ; CHECK:       exit:
67 ; CHECK-NEXT:    ret i32 -1
68 ; CHECK:       failure:
69 ; CHECK-NEXT:    unreachable
71 entry:
72   %scevgep = getelementptr i32, ptr %p, i64 -7
73   br label %loop
75 loop:                                             ; preds = %backedge, %entry
76   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
77   %iv.next = add i64 %iv, -1
78   %cond_1 = icmp eq i64 %iv, 0
79   br i1 %cond_1, label %exit, label %backedge
81 backedge:                                         ; preds = %loop
82   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
83   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
84   %cond_2 = icmp eq i32 %loaded, %x
85   br i1 %cond_2, label %failure, label %loop
87 exit:                                             ; preds = %loop
88   ret i32 -1
90 failure:                                          ; preds = %backedge
91   unreachable
94 ; TODO: We can use trick with usub here.
95 define i32 @test_02(ptr %p, i64 %len, i32 %x) {
96 ; CHECK-LABEL: @test_02(
97 ; CHECK-NEXT:  entry:
98 ; CHECK-NEXT:    br label [[LOOP:%.*]]
99 ; CHECK:       loop:
100 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
101 ; CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)
102 ; CHECK-NEXT:    [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 0
103 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
104 ; CHECK-NEXT:    br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]
105 ; CHECK:       backedge:
106 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[MATH]], 4
107 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
108 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
109 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
110 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
111 ; CHECK:       exit:
112 ; CHECK-NEXT:    ret i32 -1
113 ; CHECK:       failure:
114 ; CHECK-NEXT:    unreachable
116 entry:
117   %scevgep = getelementptr i32, ptr %p, i64 -1
118   br label %loop
120 loop:                                             ; preds = %backedge, %entry
121   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
122   %cond_1 = icmp eq i64 %iv, 0
123   br i1 %cond_1, label %exit, label %backedge
125 backedge:                                         ; preds = %loop
126   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
127   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
128   %cond_2 = icmp eq i32 %loaded, %x
129   %iv.next = add i64 %iv, -1
130   br i1 %cond_2, label %failure, label %loop
132 exit:                                             ; preds = %loop
133   ret i32 -1
135 failure:                                          ; preds = %backedge
136   unreachable
139 declare i1 @use(i64 %x)
140 declare i1 @some_cond()
142 ; Make sure we do not move the increment below the point where it is used.
143 define i32 @test_03_neg(ptr %p, i64 %len, i32 %x) {
144 ; CHECK-LABEL: @test_03_neg(
145 ; CHECK-NEXT:  entry:
146 ; CHECK-NEXT:    br label [[LOOP:%.*]]
147 ; CHECK:       loop:
148 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
149 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], -1
150 ; CHECK-NEXT:    [[COND_0:%.*]] = call i1 @use(i64 [[IV_NEXT]])
151 ; CHECK-NEXT:    br i1 [[COND_0]], label [[MIDDLE:%.*]], label [[FAILURE:%.*]]
152 ; CHECK:       middle:
153 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
154 ; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
155 ; CHECK:       backedge:
156 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4
157 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
158 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
159 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
160 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE]], label [[LOOP]]
161 ; CHECK:       exit:
162 ; CHECK-NEXT:    ret i32 -1
163 ; CHECK:       failure:
164 ; CHECK-NEXT:    unreachable
166 entry:
167   %scevgep = getelementptr i32, ptr %p, i64 -1
168   br label %loop
170 loop:                                             ; preds = %backedge, %entry
171   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
172   %iv.next = add i64 %iv, -1
173   %cond_0 = call i1 @use(i64 %iv.next)
174   br i1 %cond_0, label %middle, label %failure
176 middle:
177   %cond_1 = icmp eq i64 %iv, 0
178   br i1 %cond_1, label %exit, label %backedge
180 backedge:                                         ; preds = %loop
181   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
182   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
183   %cond_2 = icmp eq i32 %loaded, %x
184   br i1 %cond_2, label %failure, label %loop
186 exit:                                             ; preds = %loop
187   ret i32 -1
189 failure:                                          ; preds = %backedge
190   unreachable
193 define i32 @test_04_neg(ptr %p, i64 %len, i32 %x) {
194 ; CHECK-LABEL: @test_04_neg(
195 ; CHECK-NEXT:  entry:
196 ; CHECK-NEXT:    br label [[LOOP:%.*]]
197 ; CHECK:       loop:
198 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
199 ; CHECK-NEXT:    br label [[INNER:%.*]]
200 ; CHECK:       inner:
201 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
202 ; CHECK-NEXT:    br i1 [[COND_1]], label [[INNER_BACKEDGE:%.*]], label [[EXIT:%.*]]
203 ; CHECK:       inner_backedge:
204 ; CHECK-NEXT:    [[COND_INNER:%.*]] = call i1 @some_cond()
205 ; CHECK-NEXT:    br i1 [[COND_INNER]], label [[INNER]], label [[BACKEDGE]]
206 ; CHECK:       backedge:
207 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[IV]], 4
208 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
209 ; CHECK-NEXT:    [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4
210 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4
211 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
212 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], -1
213 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
214 ; CHECK:       exit:
215 ; CHECK-NEXT:    ret i32 -1
216 ; CHECK:       failure:
217 ; CHECK-NEXT:    unreachable
219 entry:
220   %scevgep = getelementptr i32, ptr %p, i64 -1
221   br label %loop
223 loop:
224   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
225   br label %inner
227 inner:
228   %cond_1 = icmp eq i64 %iv, 0
229   br i1 %cond_1, label %inner_backedge, label %exit
231 inner_backedge:
232   %cond_inner = call i1 @some_cond()
233   br i1 %cond_inner, label %inner, label %backedge
235 backedge:
236   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
237   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
238   %cond_2 = icmp eq i32 %loaded, %x
239   %iv.next = add i64 %iv, -1
240   br i1 %cond_2, label %failure, label %loop
242 exit:
243   ret i32 -1
245 failure:
246   unreachable
249 ; Here Cmp does not dominate latch.
250 define i32 @test_05_neg(ptr %p, i64 %len, i32 %x, i1 %cond) {
251 ; CHECK-LABEL: @test_05_neg(
252 ; CHECK-NEXT:  entry:
253 ; CHECK-NEXT:    br label [[LOOP:%.*]]
254 ; CHECK:       loop:
255 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
256 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], -1
257 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[BACKEDGE]]
258 ; CHECK:       if.true:
259 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
260 ; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
261 ; CHECK:       backedge:
262 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4
263 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
264 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
265 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
266 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
267 ; CHECK:       exit:
268 ; CHECK-NEXT:    ret i32 -1
269 ; CHECK:       failure:
270 ; CHECK-NEXT:    unreachable
272 entry:
273   %scevgep = getelementptr i32, ptr %p, i64 -1
274   br label %loop
276 loop:                                             ; preds = %backedge, %entry
277   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
278   %iv.next = add i64 %iv, -1
279   br i1 %cond, label %if.true, label %backedge
281 if.true:
282   %cond_1 = icmp eq i64 %iv, 0
283   br i1 %cond_1, label %exit, label %backedge
285 backedge:                                         ; preds = %loop
286   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
287   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
288   %cond_2 = icmp eq i32 %loaded, %x
289   br i1 %cond_2, label %failure, label %loop
291 exit:                                             ; preds = %loop
292   ret i32 -1
294 failure:                                          ; preds = %backedge
295   unreachable
299 ; test_01, but with an additional use of %iv.next outside the loop
300 define i32 @test_06(ptr %p, i64 %len, i32 %x) {
301 ; CHECK-LABEL: @test_06(
302 ; CHECK-NEXT:  entry:
303 ; CHECK-NEXT:    br label [[LOOP:%.*]]
304 ; CHECK:       loop:
305 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
306 ; CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)
307 ; CHECK-NEXT:    [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 0
308 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
309 ; CHECK-NEXT:    br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]
310 ; CHECK:       backedge:
311 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[MATH]], 4
312 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
313 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
314 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
315 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
316 ; CHECK:       exit:
317 ; CHECK-NEXT:    ret i32 -1
318 ; CHECK:       failure:
319 ; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[MATH]] to i32
320 ; CHECK-NEXT:    ret i32 [[TRUNC]]
322 entry:
323   %scevgep = getelementptr i32, ptr %p, i64 -1
324   br label %loop
326 loop:                                             ; preds = %backedge, %entry
327   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
328   %cond_1 = icmp eq i64 %iv, 0
329   br i1 %cond_1, label %exit, label %backedge
331 backedge:                                         ; preds = %loop
332   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
333   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
334   %iv.next = add i64 %iv, -1
335   %cond_2 = icmp eq i32 %loaded, %x
336   br i1 %cond_2, label %failure, label %loop
338 exit:
339   ret i32 -1
341 failure:
342   %trunc = trunc i64 %iv.next to i32
343   ret i32 %trunc
347 ; Extra use outside loop which prevents us moving the increment to the cmp
348 define i32 @test_07_neg(ptr %p, i64 %len, i32 %x) {
349 ; CHECK-LABEL: @test_07_neg(
350 ; CHECK-NEXT:  entry:
351 ; CHECK-NEXT:    br label [[LOOP:%.*]]
352 ; CHECK:       loop:
353 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
354 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], -1
355 ; CHECK-NEXT:    [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4
356 ; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]
357 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4
358 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
359 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[BACKEDGE]]
360 ; CHECK:       backedge:
361 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
362 ; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[LOOP]]
363 ; CHECK:       exit:
364 ; CHECK-NEXT:    ret i32 -1
365 ; CHECK:       failure:
366 ; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[IV_NEXT]] to i32
367 ; CHECK-NEXT:    ret i32 [[TRUNC]]
369 entry:
370   %scevgep = getelementptr i32, ptr %p, i64 -1
371   br label %loop
373 loop:
374   %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
375   %iv.next = add i64 %iv, -1
376   %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv
377   %loaded = load atomic i32, ptr %scevgep1 unordered, align 4
378   %cond_2 = icmp eq i32 %loaded, %x
379   br i1 %cond_2, label %failure, label %backedge
381 backedge:
382   %cond_1 = icmp eq i64 %iv, 0
383   br i1 %cond_1, label %exit, label %loop
385 exit:
386   ret i32 -1
388 failure:
389   %trunc = trunc i64 %iv.next to i32
390   ret i32 %trunc