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(
7 ; CHECK-NEXT: br label [[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]]
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]]
21 ; CHECK-NEXT: ret i32 -1
23 ; CHECK-NEXT: unreachable
26 %scevgep = getelementptr i32, ptr %p, i64 -1
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
44 failure: ; preds = %backedge
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(
52 ; CHECK-NEXT: br label [[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]]
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]]
67 ; CHECK-NEXT: ret i32 -1
69 ; CHECK-NEXT: unreachable
72 %scevgep = getelementptr i32, ptr %p, i64 -7
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
90 failure: ; preds = %backedge
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(
98 ; CHECK-NEXT: br label [[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]]
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]]
112 ; CHECK-NEXT: ret i32 -1
114 ; CHECK-NEXT: unreachable
117 %scevgep = getelementptr i32, ptr %p, i64 -1
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
135 failure: ; preds = %backedge
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(
146 ; CHECK-NEXT: br label [[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:%.*]]
153 ; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
154 ; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[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]]
162 ; CHECK-NEXT: ret i32 -1
164 ; CHECK-NEXT: unreachable
167 %scevgep = getelementptr i32, ptr %p, i64 -1
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
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
189 failure: ; preds = %backedge
193 define i32 @test_04_neg(ptr %p, i64 %len, i32 %x) {
194 ; CHECK-LABEL: @test_04_neg(
196 ; CHECK-NEXT: br label [[LOOP:%.*]]
198 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
199 ; CHECK-NEXT: br label [[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]]
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]]
215 ; CHECK-NEXT: ret i32 -1
217 ; CHECK-NEXT: unreachable
220 %scevgep = getelementptr i32, ptr %p, i64 -1
224 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
228 %cond_1 = icmp eq i64 %iv, 0
229 br i1 %cond_1, label %inner_backedge, label %exit
232 %cond_inner = call i1 @some_cond()
233 br i1 %cond_inner, label %inner, label %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
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(
253 ; CHECK-NEXT: br label [[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]]
259 ; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
260 ; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[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]]
268 ; CHECK-NEXT: ret i32 -1
270 ; CHECK-NEXT: unreachable
273 %scevgep = getelementptr i32, ptr %p, i64 -1
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
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
294 failure: ; preds = %backedge
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(
303 ; CHECK-NEXT: br label [[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]]
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]]
317 ; CHECK-NEXT: ret i32 -1
319 ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[MATH]] to i32
320 ; CHECK-NEXT: ret i32 [[TRUNC]]
323 %scevgep = getelementptr i32, ptr %p, i64 -1
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
342 %trunc = trunc i64 %iv.next to i32
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(
351 ; CHECK-NEXT: br label [[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]]
361 ; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
362 ; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[LOOP]]
364 ; CHECK-NEXT: ret i32 -1
366 ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[IV_NEXT]] to i32
367 ; CHECK-NEXT: ret i32 [[TRUNC]]
370 %scevgep = getelementptr i32, ptr %p, i64 -1
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
382 %cond_1 = icmp eq i64 %iv, 0
383 br i1 %cond_1, label %exit, label %loop
389 %trunc = trunc i64 %iv.next to i32