[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Transforms / LoopPredication / constant-ranges.ll
blob6a68f9bed3a3a6c965e3828e32e70f1a7b167f67
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(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1
8 ; CHECK-NEXT:    br label [[LOOP:%.*]]
9 ; CHECK:       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:%.*]]
21 ; CHECK:       backedge:
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:%.*]]
27 ; CHECK:       deopt:
28 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
29 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
30 ; CHECK:       exit:
31 ; CHECK-NEXT:    ret i32 0
32 ; CHECK:       bound_check_failed:
33 ; CHECK-NEXT:    ret i32 -1
35 entry:
36   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
37   br label %loop
39 loop:
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
46 do_range_check:
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
53 backedge:
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
60 deopt:
61   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
62   ret i32 %deopt_res
64 exit:
65   ret i32 0
67 bound_check_failed:
68   ret i32 -1
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(
73 ; CHECK-NEXT:  entry:
74 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
75 ; CHECK-NEXT:    br label [[LOOP:%.*]]
76 ; CHECK:       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:%.*]]
88 ; CHECK:       backedge:
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:%.*]]
94 ; CHECK:       deopt:
95 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
96 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
97 ; CHECK:       exit:
98 ; CHECK-NEXT:    ret i32 0
99 ; CHECK:       bound_check_failed:
100 ; CHECK-NEXT:    ret i32 -1
102 entry:
103   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
104   br label %loop
106 loop:
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
113 do_range_check:
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
120 backedge:
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
127 deopt:
128   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
129   ret i32 %deopt_res
131 exit:
132   ret i32 0
134 bound_check_failed:
135   ret i32 -1
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(
140 ; CHECK-NEXT:  entry:
141 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
142 ; CHECK-NEXT:    br label [[LOOP:%.*]]
143 ; CHECK:       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:%.*]]
155 ; CHECK:       backedge:
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:%.*]]
161 ; CHECK:       deopt:
162 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
163 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
164 ; CHECK:       exit:
165 ; CHECK-NEXT:    ret i32 0
166 ; CHECK:       bound_check_failed:
167 ; CHECK-NEXT:    ret i32 -1
169 entry:
170   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
171   br label %loop
173 loop:
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
180 do_range_check:
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
187 backedge:
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
194 deopt:
195   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
196   ret i32 %deopt_res
198 exit:
199   ret i32 0
201 bound_check_failed:
202   ret i32 -1
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(
207 ; CHECK-NEXT:  entry:
208 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
209 ; CHECK-NEXT:    br label [[LOOP:%.*]]
210 ; CHECK:       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:%.*]]
222 ; CHECK:       backedge:
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:%.*]]
228 ; CHECK:       deopt:
229 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
230 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
231 ; CHECK:       exit:
232 ; CHECK-NEXT:    ret i32 0
233 ; CHECK:       bound_check_failed:
234 ; CHECK-NEXT:    ret i32 -1
236 entry:
237   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
238   br label %loop
240 loop:
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
247 do_range_check:
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
254 backedge:
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
261 deopt:
262   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
263   ret i32 %deopt_res
265 exit:
266   ret i32 0
268 bound_check_failed:
269   ret i32 -1
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(
274 ; CHECK-NEXT:  entry:
275 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
276 ; CHECK-NEXT:    br label [[LOOP:%.*]]
277 ; CHECK:       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:%.*]]
289 ; CHECK:       backedge:
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:%.*]]
295 ; CHECK:       deopt:
296 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
297 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
298 ; CHECK:       exit:
299 ; CHECK-NEXT:    ret i32 0
300 ; CHECK:       bound_check_failed:
301 ; CHECK-NEXT:    ret i32 -1
303 entry:
304   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
305   br label %loop
307 loop:
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
314 do_range_check:
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
321 backedge:
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
328 deopt:
329   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
330   ret i32 %deopt_res
332 exit:
333   ret i32 0
335 bound_check_failed:
336   ret i32 -1
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(
341 ; CHECK-NEXT:  entry:
342 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
343 ; CHECK-NEXT:    br label [[LOOP:%.*]]
344 ; CHECK:       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:%.*]]
356 ; CHECK:       backedge:
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:%.*]]
362 ; CHECK:       deopt:
363 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
364 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
365 ; CHECK:       exit:
366 ; CHECK-NEXT:    ret i32 0
367 ; CHECK:       bound_check_failed:
368 ; CHECK-NEXT:    ret i32 -1
370 entry:
371   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
372   br label %loop
374 loop:
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
381 do_range_check:
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
388 backedge:
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
395 deopt:
396   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
397   ret i32 %deopt_res
399 exit:
400   ret i32 0
402 bound_check_failed:
403   ret i32 -1
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(
408 ; CHECK-NEXT:  entry:
409 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
410 ; CHECK-NEXT:    br label [[LOOP:%.*]]
411 ; CHECK:       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:%.*]]
423 ; CHECK:       backedge:
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:%.*]]
429 ; CHECK:       deopt:
430 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
431 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
432 ; CHECK:       exit:
433 ; CHECK-NEXT:    ret i32 0
434 ; CHECK:       bound_check_failed:
435 ; CHECK-NEXT:    ret i32 -1
437 entry:
438   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
439   br label %loop
441 loop:
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
448 do_range_check:
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
455 backedge:
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
462 deopt:
463   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
464   ret i32 %deopt_res
466 exit:
467   ret i32 0
469 bound_check_failed:
470   ret i32 -1
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(
475 ; CHECK-NEXT:  entry:
476 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1
477 ; CHECK-NEXT:    br label [[LOOP:%.*]]
478 ; CHECK:       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:%.*]]
490 ; CHECK:       backedge:
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:%.*]]
496 ; CHECK:       deopt:
497 ; CHECK-NEXT:    [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
498 ; CHECK-NEXT:    ret i32 [[DEOPT_RES]]
499 ; CHECK:       exit:
500 ; CHECK-NEXT:    ret i32 0
501 ; CHECK:       bound_check_failed:
502 ; CHECK-NEXT:    ret i32 -1
504 entry:
505   %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1
506   br label %loop
508 loop:
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
515 do_range_check:
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
522 backedge:
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
529 deopt:
530   %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
531   ret i32 %deopt_res
533 exit:
534   ret i32 0
536 bound_check_failed:
537   ret i32 -1
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 }
549 !0 = !{}
550 !1 = !{i32 0, i32 2147483646}