1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes='loop-mssa(loop-predication)' -loop-predication-insert-assumes-of-predicated-guards-conditions=false < %s 2>&1 | FileCheck %s
4 define i32 @test_ult(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
5 ; CHECK-LABEL: @test_ult(
7 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1
8 ; CHECK-NEXT: br label [[LOOP:%.*]]
10 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
11 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
12 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
13 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128
14 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
15 ; CHECK: do_range_check:
16 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
17 ; CHECK-NEXT: [[RANGE_CHECK_ULT:%.*]] = icmp ult i32 [[EL]], [[LEN]]
18 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
19 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULT]], [[WC]]
20 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
22 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
23 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
24 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
25 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
26 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
28 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
29 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
31 ; CHECK-NEXT: ret i32 0
32 ; CHECK: bound_check_failed:
33 ; CHECK-NEXT: ret i32 -1
36 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
40 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
41 %el.ptr = getelementptr i32, ptr %p, i32 %iv
42 %el = load i32, ptr %el.ptr, align 4
43 %bound_check = icmp ult i32 %el, 128
44 br i1 %bound_check, label %do_range_check, label %bound_check_failed
47 call void @llvm.assume(i1 %bound_check)
48 %range_check.ult = icmp ult i32 %el, %len
49 %wc = call i1 @llvm.experimental.widenable.condition()
50 %explicit_guard_cond = and i1 %range_check.ult, %wc
51 br i1 %explicit_guard_cond, label %backedge, label %deopt
54 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
55 store i32 %iv, ptr %arr.ptr, align 4
56 %iv.next = add i32 %iv, 1
57 %loop_cond = icmp slt i32 %iv.next, %n
58 br i1 %loop_cond, label %loop, label %exit
61 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
71 define i32 @test_slt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
72 ; CHECK-LABEL: @test_slt(
74 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
75 ; CHECK-NEXT: br label [[LOOP:%.*]]
77 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
78 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
79 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
80 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128
81 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
82 ; CHECK: do_range_check:
83 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
84 ; CHECK-NEXT: [[RANGE_CHECK_SLT:%.*]] = icmp slt i32 [[EL]], [[LEN]]
85 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
86 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLT]], [[WC]]
87 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
89 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
90 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
91 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
92 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
93 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
95 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
96 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
98 ; CHECK-NEXT: ret i32 0
99 ; CHECK: bound_check_failed:
100 ; CHECK-NEXT: ret i32 -1
103 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
107 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
108 %el.ptr = getelementptr i32, ptr %p, i32 %iv
109 %el = load i32, ptr %el.ptr, align 4
110 %bound_check = icmp slt i32 %el, 128
111 br i1 %bound_check, label %do_range_check, label %bound_check_failed
114 call void @llvm.assume(i1 %bound_check)
115 %range_check.slt = icmp slt i32 %el, %len
116 %wc = call i1 @llvm.experimental.widenable.condition()
117 %explicit_guard_cond = and i1 %range_check.slt, %wc
118 br i1 %explicit_guard_cond, label %backedge, label %deopt
121 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
122 store i32 %iv, ptr %arr.ptr, align 4
123 %iv.next = add i32 %iv, 1
124 %loop_cond = icmp ult i32 %iv.next, %n
125 br i1 %loop_cond, label %loop, label %exit
128 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
138 define i32 @test_ule(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
139 ; CHECK-LABEL: @test_ule(
141 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
142 ; CHECK-NEXT: br label [[LOOP:%.*]]
144 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
145 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
146 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
147 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128
148 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
149 ; CHECK: do_range_check:
150 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
151 ; CHECK-NEXT: [[RANGE_CHECK_ULE:%.*]] = icmp ule i32 [[EL]], [[LEN]]
152 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
153 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULE]], [[WC]]
154 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
156 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
157 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
158 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
159 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
160 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
162 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
163 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
165 ; CHECK-NEXT: ret i32 0
166 ; CHECK: bound_check_failed:
167 ; CHECK-NEXT: ret i32 -1
170 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
174 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
175 %el.ptr = getelementptr i32, ptr %p, i32 %iv
176 %el = load i32, ptr %el.ptr, align 4
177 %bound_check = icmp ult i32 %el, 128
178 br i1 %bound_check, label %do_range_check, label %bound_check_failed
181 call void @llvm.assume(i1 %bound_check)
182 %range_check.ule = icmp ule i32 %el, %len
183 %wc = call i1 @llvm.experimental.widenable.condition()
184 %explicit_guard_cond = and i1 %range_check.ule, %wc
185 br i1 %explicit_guard_cond, label %backedge, label %deopt
188 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
189 store i32 %iv, ptr %arr.ptr, align 4
190 %iv.next = add i32 %iv, 1
191 %loop_cond = icmp ult i32 %iv.next, %n
192 br i1 %loop_cond, label %loop, label %exit
195 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
205 define i32 @test_sle(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
206 ; CHECK-LABEL: @test_sle(
208 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
209 ; CHECK-NEXT: br label [[LOOP:%.*]]
211 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
212 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
213 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
214 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128
215 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
216 ; CHECK: do_range_check:
217 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
218 ; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sle i32 [[EL]], [[LEN]]
219 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
220 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]]
221 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
223 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
224 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
225 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
226 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
227 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
229 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
230 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
232 ; CHECK-NEXT: ret i32 0
233 ; CHECK: bound_check_failed:
234 ; CHECK-NEXT: ret i32 -1
237 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
241 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
242 %el.ptr = getelementptr i32, ptr %p, i32 %iv
243 %el = load i32, ptr %el.ptr, align 4
244 %bound_check = icmp slt i32 %el, 128
245 br i1 %bound_check, label %do_range_check, label %bound_check_failed
248 call void @llvm.assume(i1 %bound_check)
249 %range_check.sle = icmp sle i32 %el, %len
250 %wc = call i1 @llvm.experimental.widenable.condition()
251 %explicit_guard_cond = and i1 %range_check.sle, %wc
252 br i1 %explicit_guard_cond, label %backedge, label %deopt
255 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
256 store i32 %iv, ptr %arr.ptr, align 4
257 %iv.next = add i32 %iv, 1
258 %loop_cond = icmp ult i32 %iv.next, %n
259 br i1 %loop_cond, label %loop, label %exit
262 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
272 define i32 @test_ugt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
273 ; CHECK-LABEL: @test_ugt(
275 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
276 ; CHECK-NEXT: br label [[LOOP:%.*]]
278 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
279 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
280 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
281 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128
282 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
283 ; CHECK: do_range_check:
284 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
285 ; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp ugt i32 [[LEN]], [[EL]]
286 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
287 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]]
288 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
290 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
291 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
292 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
293 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
294 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
296 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
297 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
299 ; CHECK-NEXT: ret i32 0
300 ; CHECK: bound_check_failed:
301 ; CHECK-NEXT: ret i32 -1
304 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
308 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
309 %el.ptr = getelementptr i32, ptr %p, i32 %iv
310 %el = load i32, ptr %el.ptr, align 4
311 %bound_check = icmp ult i32 %el, 128
312 br i1 %bound_check, label %do_range_check, label %bound_check_failed
315 call void @llvm.assume(i1 %bound_check)
316 %range_check.sle = icmp ugt i32 %len, %el
317 %wc = call i1 @llvm.experimental.widenable.condition()
318 %explicit_guard_cond = and i1 %range_check.sle, %wc
319 br i1 %explicit_guard_cond, label %backedge, label %deopt
322 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
323 store i32 %iv, ptr %arr.ptr, align 4
324 %iv.next = add i32 %iv, 1
325 %loop_cond = icmp ult i32 %iv.next, %n
326 br i1 %loop_cond, label %loop, label %exit
329 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
339 define i32 @test_uge(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
340 ; CHECK-LABEL: @test_uge(
342 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
343 ; CHECK-NEXT: br label [[LOOP:%.*]]
345 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
346 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
347 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
348 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128
349 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
350 ; CHECK: do_range_check:
351 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
352 ; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp uge i32 [[LEN]], [[EL]]
353 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
354 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]]
355 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
357 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
358 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
359 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
360 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
361 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
363 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
364 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
366 ; CHECK-NEXT: ret i32 0
367 ; CHECK: bound_check_failed:
368 ; CHECK-NEXT: ret i32 -1
371 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
375 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
376 %el.ptr = getelementptr i32, ptr %p, i32 %iv
377 %el = load i32, ptr %el.ptr, align 4
378 %bound_check = icmp ult i32 %el, 128
379 br i1 %bound_check, label %do_range_check, label %bound_check_failed
382 call void @llvm.assume(i1 %bound_check)
383 %range_check.sle = icmp uge i32 %len, %el
384 %wc = call i1 @llvm.experimental.widenable.condition()
385 %explicit_guard_cond = and i1 %range_check.sle, %wc
386 br i1 %explicit_guard_cond, label %backedge, label %deopt
389 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
390 store i32 %iv, ptr %arr.ptr, align 4
391 %iv.next = add i32 %iv, 1
392 %loop_cond = icmp ult i32 %iv.next, %n
393 br i1 %loop_cond, label %loop, label %exit
396 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
406 define i32 @test_sgt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
407 ; CHECK-LABEL: @test_sgt(
409 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
410 ; CHECK-NEXT: br label [[LOOP:%.*]]
412 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
413 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
414 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
415 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128
416 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
417 ; CHECK: do_range_check:
418 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
419 ; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sgt i32 [[LEN]], [[EL]]
420 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
421 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]]
422 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
424 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
425 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
426 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
427 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
428 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
430 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
431 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
433 ; CHECK-NEXT: ret i32 0
434 ; CHECK: bound_check_failed:
435 ; CHECK-NEXT: ret i32 -1
438 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
442 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
443 %el.ptr = getelementptr i32, ptr %p, i32 %iv
444 %el = load i32, ptr %el.ptr, align 4
445 %bound_check = icmp slt i32 %el, 128
446 br i1 %bound_check, label %do_range_check, label %bound_check_failed
449 call void @llvm.assume(i1 %bound_check)
450 %range_check.sle = icmp sgt i32 %len, %el
451 %wc = call i1 @llvm.experimental.widenable.condition()
452 %explicit_guard_cond = and i1 %range_check.sle, %wc
453 br i1 %explicit_guard_cond, label %backedge, label %deopt
456 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
457 store i32 %iv, ptr %arr.ptr, align 4
458 %iv.next = add i32 %iv, 1
459 %loop_cond = icmp ult i32 %iv.next, %n
460 br i1 %loop_cond, label %loop, label %exit
463 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
473 define i32 @test_sge(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) {
474 ; CHECK-LABEL: @test_sge(
476 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
477 ; CHECK-NEXT: br label [[LOOP:%.*]]
479 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
480 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
481 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
482 ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128
483 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]]
484 ; CHECK: do_range_check:
485 ; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]])
486 ; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sge i32 [[LEN]], [[EL]]
487 ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
488 ; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]]
489 ; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]]
491 ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
492 ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
493 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
494 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
495 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
497 ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
498 ; CHECK-NEXT: ret i32 [[DEOPT_RES]]
500 ; CHECK-NEXT: ret i32 0
501 ; CHECK: bound_check_failed:
502 ; CHECK-NEXT: ret i32 -1
505 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
509 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
510 %el.ptr = getelementptr i32, ptr %p, i32 %iv
511 %el = load i32, ptr %el.ptr, align 4
512 %bound_check = icmp slt i32 %el, 128
513 br i1 %bound_check, label %do_range_check, label %bound_check_failed
516 call void @llvm.assume(i1 %bound_check)
517 %range_check.sle = icmp sge i32 %len, %el
518 %wc = call i1 @llvm.experimental.widenable.condition()
519 %explicit_guard_cond = and i1 %range_check.sle, %wc
520 br i1 %explicit_guard_cond, label %backedge, label %deopt
523 %arr.ptr = getelementptr i32, ptr %arr, i32 %el
524 store i32 %iv, ptr %arr.ptr, align 4
525 %iv.next = add i32 %iv, 1
526 %loop_cond = icmp ult i32 %iv.next, %n
527 br i1 %loop_cond, label %loop, label %exit
530 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
540 ; Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn
541 declare i1 @llvm.experimental.widenable.condition() #1
543 declare i32 @llvm.experimental.deoptimize.i32(...)
545 declare void @llvm.assume(i1)
547 attributes #1 = { inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn }
550 !1 = !{i32 0, i32 2147483646}