1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=loop-predication < %s 2>&1 | FileCheck %s
3 ; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
5 declare void @llvm.experimental.guard(i1, ...)
7 define i32 @unsigned_loop_0_to_n_ult_check(ptr %array, i32 %length, i32 %n) {
8 ; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check(
10 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
11 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
12 ; CHECK: loop.preheader:
13 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
14 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
15 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
16 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
17 ; CHECK-NEXT: br label [[LOOP:%.*]]
19 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
20 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
21 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
22 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
23 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
24 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
25 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
26 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
27 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
28 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
29 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
30 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
31 ; CHECK: exit.loopexit:
32 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
33 ; CHECK-NEXT: br label [[EXIT]]
35 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
36 ; CHECK-NEXT: ret i32 [[RESULT]]
39 %tmp5 = icmp eq i32 %n, 0
40 br i1 %tmp5, label %exit, label %loop.preheader
46 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
47 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
48 %within.bounds = icmp ult i32 %i, %length
49 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
51 %i.i64 = zext i32 %i to i64
52 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
53 %array.i = load i32, ptr %array.i.ptr, align 4
54 %loop.acc.next = add i32 %loop.acc, %array.i
56 %i.next = add nuw i32 %i, 1
57 %continue = icmp ult i32 %i.next, %n
58 br i1 %continue, label %loop, label %exit
61 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
65 define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(ptr %array, i32 %length, i32 %n) {
66 ; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check(
68 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
69 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
70 ; CHECK: loop.preheader:
71 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]]
72 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
73 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
74 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
75 ; CHECK-NEXT: br label [[LOOP:%.*]]
77 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
78 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
79 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
80 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
81 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
82 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
83 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
84 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
85 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
86 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
87 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]]
88 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
89 ; CHECK: exit.loopexit:
90 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
91 ; CHECK-NEXT: br label [[EXIT]]
93 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
94 ; CHECK-NEXT: ret i32 [[RESULT]]
97 %tmp5 = icmp eq i32 %n, 0
98 br i1 %tmp5, label %exit, label %loop.preheader
104 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
105 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
106 %within.bounds = icmp ult i32 %i, %length
107 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
109 %i.i64 = zext i32 %i to i64
110 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
111 %array.i = load i32, ptr %array.i.ptr, align 4
112 %loop.acc.next = add i32 %loop.acc, %array.i
114 %i.next = add nuw i32 %i, 1
115 %continue = icmp ule i32 %i.next, %n
116 br i1 %continue, label %loop, label %exit
119 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
123 define i32 @unsigned_loop_0_to_n_ugt_check(ptr %array, i32 %length, i32 %n) {
124 ; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check(
126 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
127 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
128 ; CHECK: loop.preheader:
129 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
130 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
131 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
132 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
133 ; CHECK-NEXT: br label [[LOOP:%.*]]
135 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
136 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
137 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ugt i32 [[LENGTH]], [[I]]
138 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
139 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
140 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
141 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
142 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
143 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
144 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
145 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
146 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
147 ; CHECK: exit.loopexit:
148 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
149 ; CHECK-NEXT: br label [[EXIT]]
151 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
152 ; CHECK-NEXT: ret i32 [[RESULT]]
155 %tmp5 = icmp eq i32 %n, 0
156 br i1 %tmp5, label %exit, label %loop.preheader
162 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
163 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
164 %within.bounds = icmp ugt i32 %length, %i
165 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
167 %i.i64 = zext i32 %i to i64
168 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
169 %array.i = load i32, ptr %array.i.ptr, align 4
170 %loop.acc.next = add i32 %loop.acc, %array.i
172 %i.next = add nuw i32 %i, 1
173 %continue = icmp ult i32 %i.next, %n
174 br i1 %continue, label %loop, label %exit
177 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
181 define i32 @signed_loop_0_to_n_ult_check(ptr %array, i32 %length, i32 %n) {
182 ; CHECK-LABEL: @signed_loop_0_to_n_ult_check(
184 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
185 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
186 ; CHECK: loop.preheader:
187 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
188 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
189 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
190 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
191 ; CHECK-NEXT: br label [[LOOP:%.*]]
193 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
194 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
195 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
196 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
197 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
198 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
199 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
200 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
201 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
202 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
203 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
204 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
205 ; CHECK: exit.loopexit:
206 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
207 ; CHECK-NEXT: br label [[EXIT]]
209 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
210 ; CHECK-NEXT: ret i32 [[RESULT]]
213 %tmp5 = icmp sle i32 %n, 0
214 br i1 %tmp5, label %exit, label %loop.preheader
220 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
221 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
222 %within.bounds = icmp ult i32 %i, %length
223 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
225 %i.i64 = zext i32 %i to i64
226 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
227 %array.i = load i32, ptr %array.i.ptr, align 4
228 %loop.acc.next = add i32 %loop.acc, %array.i
230 %i.next = add nuw i32 %i, 1
231 %continue = icmp slt i32 %i.next, %n
232 br i1 %continue, label %loop, label %exit
235 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
239 define i32 @signed_loop_0_to_n_ult_check_length_range_known(ptr %array, ptr %length.ptr, i32 %n) {
240 ; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known(
242 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
243 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]]
244 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
245 ; CHECK: loop.preheader:
246 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]]
247 ; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]]
248 ; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
249 ; CHECK-NEXT: br label [[LOOP:%.*]]
251 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
252 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
253 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
254 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
255 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
256 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
257 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
258 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
259 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
260 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
261 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
262 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
263 ; CHECK: exit.loopexit:
264 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
265 ; CHECK-NEXT: br label [[EXIT]]
267 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
268 ; CHECK-NEXT: ret i32 [[RESULT]]
271 %tmp5 = icmp sle i32 %n, 0
272 %length = load i32, ptr %length.ptr, !range !{i32 1, i32 2147483648}
273 br i1 %tmp5, label %exit, label %loop.preheader
279 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
280 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
281 %within.bounds = icmp ult i32 %i, %length
282 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
284 %i.i64 = zext i32 %i to i64
285 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
286 %array.i = load i32, ptr %array.i.ptr, align 4
287 %loop.acc.next = add i32 %loop.acc, %array.i
289 %i.next = add nuw i32 %i, 1
290 %continue = icmp slt i32 %i.next, %n
291 br i1 %continue, label %loop, label %exit
294 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
298 define i32 @signed_loop_0_to_n_inverse_latch_predicate(ptr %array, i32 %length, i32 %n) {
299 ; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate(
301 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
302 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
303 ; CHECK: loop.preheader:
304 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
305 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
306 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
307 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
308 ; CHECK-NEXT: br label [[LOOP:%.*]]
310 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
311 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
312 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
313 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
314 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
315 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
316 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
317 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
318 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
319 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
320 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]]
321 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
322 ; CHECK: exit.loopexit:
323 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
324 ; CHECK-NEXT: br label [[EXIT]]
326 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
327 ; CHECK-NEXT: ret i32 [[RESULT]]
330 %tmp5 = icmp sle i32 %n, 0
331 br i1 %tmp5, label %exit, label %loop.preheader
337 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
338 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
339 %within.bounds = icmp ult i32 %i, %length
340 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
342 %i.i64 = zext i32 %i to i64
343 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
344 %array.i = load i32, ptr %array.i.ptr, align 4
345 %loop.acc.next = add i32 %loop.acc, %array.i
347 %i.next = add nuw i32 %i, 1
348 %continue = icmp sgt i32 %i.next, %n
349 br i1 %continue, label %exit, label %loop
352 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
356 define i32 @signed_loop_0_to_n_sle_latch_ult_check(ptr %array, i32 %length, i32 %n) {
357 ; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check(
359 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
360 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
361 ; CHECK: loop.preheader:
362 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
363 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
364 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
365 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
366 ; CHECK-NEXT: br label [[LOOP:%.*]]
368 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
369 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
370 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
371 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
372 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
373 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
374 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
375 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
376 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
377 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
378 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
379 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
380 ; CHECK: exit.loopexit:
381 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
382 ; CHECK-NEXT: br label [[EXIT]]
384 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
385 ; CHECK-NEXT: ret i32 [[RESULT]]
388 %tmp5 = icmp sle i32 %n, 0
389 br i1 %tmp5, label %exit, label %loop.preheader
395 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
396 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
397 %within.bounds = icmp ult i32 %i, %length
398 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
400 %i.i64 = zext i32 %i to i64
401 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
402 %array.i = load i32, ptr %array.i.ptr, align 4
403 %loop.acc.next = add i32 %loop.acc, %array.i
405 %i.next = add nuw i32 %i, 1
406 %continue = icmp sle i32 %i.next, %n
407 br i1 %continue, label %loop, label %exit
410 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
414 define i32 @signed_loop_0_to_n_preincrement_latch_check(ptr %array, i32 %length, i32 %n) {
415 ; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check(
417 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
418 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
419 ; CHECK: loop.preheader:
420 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
421 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
422 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
423 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
424 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
425 ; CHECK-NEXT: br label [[LOOP:%.*]]
427 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
428 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
429 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
430 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
431 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
432 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
433 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
434 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
435 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
436 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
437 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
438 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
439 ; CHECK: exit.loopexit:
440 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
441 ; CHECK-NEXT: br label [[EXIT]]
443 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
444 ; CHECK-NEXT: ret i32 [[RESULT]]
447 %tmp5 = icmp sle i32 %n, 0
448 br i1 %tmp5, label %exit, label %loop.preheader
454 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
455 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
456 %within.bounds = icmp ult i32 %i, %length
457 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
459 %i.i64 = zext i32 %i to i64
460 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
461 %array.i = load i32, ptr %array.i.ptr, align 4
462 %loop.acc.next = add i32 %loop.acc, %array.i
464 %i.next = add i32 %i, 1
465 %continue = icmp slt i32 %i, %n
466 br i1 %continue, label %loop, label %exit
469 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
473 define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(ptr %array, i32 %length, i32 %n) {
474 ; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(
476 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
477 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
478 ; CHECK: loop.preheader:
479 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2
480 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
481 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
482 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
483 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
484 ; CHECK-NEXT: br label [[LOOP:%.*]]
486 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
487 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
488 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
489 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
490 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
491 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
492 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
493 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
494 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
495 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
496 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
497 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
498 ; CHECK: exit.loopexit:
499 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
500 ; CHECK-NEXT: br label [[EXIT]]
502 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
503 ; CHECK-NEXT: ret i32 [[RESULT]]
506 %tmp5 = icmp sle i32 %n, 0
507 br i1 %tmp5, label %exit, label %loop.preheader
513 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
514 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
516 %i.next = add i32 %i, 1
517 %within.bounds = icmp ult i32 %i.next, %length
518 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
520 %i.i64 = zext i32 %i to i64
521 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
522 %array.i = load i32, ptr %array.i.ptr, align 4
523 %loop.acc.next = add i32 %loop.acc, %array.i
525 %continue = icmp slt i32 %i, %n
526 br i1 %continue, label %loop, label %exit
529 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
533 define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(ptr %array, i32 %length, i32 %n) {
534 ; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check(
536 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
537 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
538 ; CHECK: loop.preheader:
539 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
540 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]]
541 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
542 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
543 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
544 ; CHECK-NEXT: br label [[LOOP:%.*]]
546 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
547 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
548 ; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1
549 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]]
550 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
551 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
552 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
553 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
554 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
555 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
556 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
557 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
558 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
559 ; CHECK: exit.loopexit:
560 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
561 ; CHECK-NEXT: br label [[EXIT]]
563 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
564 ; CHECK-NEXT: ret i32 [[RESULT]]
567 %tmp5 = icmp sle i32 %n, 0
568 br i1 %tmp5, label %exit, label %loop.preheader
574 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
575 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
576 %i.offset = add i32 %i, 1
577 %within.bounds = icmp ult i32 %i.offset, %length
578 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
580 %i.i64 = zext i32 %i to i64
581 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
582 %array.i = load i32, ptr %array.i.ptr, align 4
583 %loop.acc.next = add i32 %loop.acc, %array.i
585 %i.next = add i32 %i, 1
586 %continue = icmp sle i32 %i.next, %n
587 br i1 %continue, label %loop, label %exit
590 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
594 define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(ptr %array, i32 %length, i32 %n) {
595 ; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(
597 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
598 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
599 ; CHECK: loop.preheader:
600 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
601 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]]
602 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
603 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
604 ; CHECK-NEXT: br label [[LOOP:%.*]]
606 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
607 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
608 ; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1
609 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]]
610 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
611 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
612 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
613 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
614 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
615 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
616 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
617 ; CHECK-NEXT: [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1
618 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]]
619 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
620 ; CHECK: exit.loopexit:
621 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
622 ; CHECK-NEXT: br label [[EXIT]]
624 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
625 ; CHECK-NEXT: ret i32 [[RESULT]]
628 %tmp5 = icmp sle i32 %n, 0
629 br i1 %tmp5, label %exit, label %loop.preheader
635 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
636 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
637 %i.offset = add i32 %i, 1
638 %within.bounds = icmp ult i32 %i.offset, %length
639 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
641 %i.i64 = zext i32 %i to i64
642 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
643 %array.i = load i32, ptr %array.i.ptr, align 4
644 %loop.acc.next = add i32 %loop.acc, %array.i
646 %i.next = add i32 %i, 1
647 %i.next.offset = add i32 %i.next, 1
648 %continue = icmp sle i32 %i.next.offset, %n
649 br i1 %continue, label %loop, label %exit
652 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
656 define i32 @unsupported_latch_pred_loop_0_to_n(ptr %array, i32 %length, i32 %n) {
657 ; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n(
659 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
660 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
661 ; CHECK: loop.preheader:
662 ; CHECK-NEXT: br label [[LOOP:%.*]]
664 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
665 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
666 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
667 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
668 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
669 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
670 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
671 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
672 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
673 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
674 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
675 ; CHECK: exit.loopexit:
676 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
677 ; CHECK-NEXT: br label [[EXIT]]
679 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
680 ; CHECK-NEXT: ret i32 [[RESULT]]
683 %tmp5 = icmp sle i32 %n, 0
684 br i1 %tmp5, label %exit, label %loop.preheader
690 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
691 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
692 %within.bounds = icmp ult i32 %i, %length
693 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
695 %i.i64 = zext i32 %i to i64
696 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
697 %array.i = load i32, ptr %array.i.ptr, align 4
698 %loop.acc.next = add i32 %loop.acc, %array.i
700 %i.next = add nsw i32 %i, 1
701 %continue = icmp ne i32 %i.next, %n
702 br i1 %continue, label %loop, label %exit
705 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
709 define i32 @signed_loop_0_to_n_unsupported_iv_step(ptr %array, i32 %length, i32 %n) {
710 ; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step(
712 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
713 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
714 ; CHECK: loop.preheader:
715 ; CHECK-NEXT: br label [[LOOP:%.*]]
717 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
718 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
719 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
720 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
721 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
722 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
723 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
724 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
725 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 2
726 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
727 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
728 ; CHECK: exit.loopexit:
729 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
730 ; CHECK-NEXT: br label [[EXIT]]
732 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
733 ; CHECK-NEXT: ret i32 [[RESULT]]
736 %tmp5 = icmp sle i32 %n, 0
737 br i1 %tmp5, label %exit, label %loop.preheader
743 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
744 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
745 %within.bounds = icmp ult i32 %i, %length
746 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
748 %i.i64 = zext i32 %i to i64
749 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
750 %array.i = load i32, ptr %array.i.ptr, align 4
751 %loop.acc.next = add i32 %loop.acc, %array.i
753 %i.next = add nsw i32 %i, 2
754 %continue = icmp slt i32 %i.next, %n
755 br i1 %continue, label %loop, label %exit
758 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
762 define i32 @signed_loop_0_to_n_equal_iv_range_check(ptr %array, i32 %length, i32 %n) {
763 ; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check(
765 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
766 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
767 ; CHECK: loop.preheader:
768 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
769 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
770 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
771 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
772 ; CHECK-NEXT: br label [[LOOP:%.*]]
774 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
775 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
776 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
777 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
778 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
779 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
780 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
781 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
782 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
783 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
784 ; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1
785 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
786 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
787 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
788 ; CHECK: exit.loopexit:
789 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
790 ; CHECK-NEXT: br label [[EXIT]]
792 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
793 ; CHECK-NEXT: ret i32 [[RESULT]]
796 %tmp5 = icmp sle i32 %n, 0
797 br i1 %tmp5, label %exit, label %loop.preheader
803 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
804 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
805 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
807 %within.bounds = icmp ult i32 %j, %length
808 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
810 %i.i64 = zext i32 %i to i64
811 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
812 %array.i = load i32, ptr %array.i.ptr, align 4
813 %loop.acc.next = add i32 %loop.acc, %array.i
815 %j.next = add nsw i32 %j, 1
816 %i.next = add nsw i32 %i, 1
817 %continue = icmp slt i32 %i.next, %n
818 br i1 %continue, label %loop, label %exit
821 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
825 define i32 @signed_loop_start_to_n_offset_iv_range_check(ptr %array, i32 %start.i,
826 ; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check(
828 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
829 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
830 ; CHECK: loop.preheader:
831 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]]
832 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]]
833 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]]
834 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]]
835 ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]]
836 ; CHECK-NEXT: [[TMP5:%.*]] = freeze i1 [[TMP4]]
837 ; CHECK-NEXT: br label [[LOOP:%.*]]
839 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
840 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START_I]], [[LOOP_PREHEADER]] ]
841 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ]
842 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
843 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ]
844 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
845 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
846 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
847 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
848 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
849 ; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
850 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
851 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
852 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
853 ; CHECK: exit.loopexit:
854 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
855 ; CHECK-NEXT: br label [[EXIT]]
857 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
858 ; CHECK-NEXT: ret i32 [[RESULT]]
860 i32 %start.j, i32 %length,
863 %tmp5 = icmp sle i32 %n, 0
864 br i1 %tmp5, label %exit, label %loop.preheader
870 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
871 %i = phi i32 [ %i.next, %loop ], [ %start.i, %loop.preheader ]
872 %j = phi i32 [ %j.next, %loop ], [ %start.j, %loop.preheader ]
874 %within.bounds = icmp ult i32 %j, %length
875 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
877 %i.i64 = zext i32 %i to i64
878 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
879 %array.i = load i32, ptr %array.i.ptr, align 4
880 %loop.acc.next = add i32 %loop.acc, %array.i
882 %j.next = add i32 %j, 1
883 %i.next = add i32 %i, 1
884 %continue = icmp slt i32 %i.next, %n
885 br i1 %continue, label %loop, label %exit
888 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
892 define i32 @signed_loop_0_to_n_different_iv_types(ptr %array, i16 %length, i32 %n) {
893 ; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types(
895 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
896 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
897 ; CHECK: loop.preheader:
898 ; CHECK-NEXT: br label [[LOOP:%.*]]
900 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
901 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
902 ; CHECK-NEXT: [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
903 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]]
904 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
905 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
906 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
907 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
908 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
909 ; CHECK-NEXT: [[J_NEXT]] = add i16 [[J]], 1
910 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
911 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
912 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
913 ; CHECK: exit.loopexit:
914 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
915 ; CHECK-NEXT: br label [[EXIT]]
917 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
918 ; CHECK-NEXT: ret i32 [[RESULT]]
921 %tmp5 = icmp sle i32 %n, 0
922 br i1 %tmp5, label %exit, label %loop.preheader
928 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
929 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
930 %j = phi i16 [ %j.next, %loop ], [ 0, %loop.preheader ]
932 %within.bounds = icmp ult i16 %j, %length
933 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
935 %i.i64 = zext i32 %i to i64
936 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
937 %array.i = load i32, ptr %array.i.ptr, align 4
938 %loop.acc.next = add i32 %loop.acc, %array.i
940 %j.next = add i16 %j, 1
941 %i.next = add i32 %i, 1
942 %continue = icmp slt i32 %i.next, %n
943 br i1 %continue, label %loop, label %exit
946 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
950 define i32 @signed_loop_0_to_n_different_iv_strides(ptr %array, i32 %length, i32 %n) {
951 ; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides(
953 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
954 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
955 ; CHECK: loop.preheader:
956 ; CHECK-NEXT: br label [[LOOP:%.*]]
958 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
959 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
960 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
961 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]]
962 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
963 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
964 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
965 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
966 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
967 ; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 2
968 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
969 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
970 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
971 ; CHECK: exit.loopexit:
972 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
973 ; CHECK-NEXT: br label [[EXIT]]
975 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
976 ; CHECK-NEXT: ret i32 [[RESULT]]
979 %tmp5 = icmp sle i32 %n, 0
980 br i1 %tmp5, label %exit, label %loop.preheader
986 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
987 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
988 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
990 %within.bounds = icmp ult i32 %j, %length
991 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
993 %i.i64 = zext i32 %i to i64
994 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
995 %array.i = load i32, ptr %array.i.ptr, align 4
996 %loop.acc.next = add i32 %loop.acc, %array.i
998 %j.next = add nsw i32 %j, 2
999 %i.next = add nsw i32 %i, 1
1000 %continue = icmp slt i32 %i.next, %n
1001 br i1 %continue, label %loop, label %exit
1004 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1008 define i32 @two_range_checks(ptr %array.1, i32 %length.1,
1009 ; CHECK-LABEL: @two_range_checks(
1010 ; CHECK-NEXT: entry:
1011 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1012 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1013 ; CHECK: loop.preheader:
1014 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1015 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1016 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1017 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1018 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1019 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1020 ; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1021 ; CHECK-NEXT: [[TMP7:%.*]] = freeze i1 [[TMP6]]
1022 ; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP3]], [[TMP7]]
1023 ; CHECK-NEXT: br label [[LOOP:%.*]]
1025 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1026 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1027 ; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1028 ; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1029 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]]
1030 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ]
1031 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1032 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1033 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1034 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1035 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1036 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1037 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1038 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1039 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1040 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1041 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1042 ; CHECK: exit.loopexit:
1043 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1044 ; CHECK-NEXT: br label [[EXIT]]
1046 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1047 ; CHECK-NEXT: ret i32 [[RESULT]]
1049 ptr %array.2, i32 %length.2, i32 %n) {
1051 %tmp5 = icmp eq i32 %n, 0
1052 br i1 %tmp5, label %exit, label %loop.preheader
1058 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1059 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1060 %within.bounds.1 = icmp ult i32 %i, %length.1
1061 %within.bounds.2 = icmp ult i32 %i, %length.2
1062 %within.bounds = and i1 %within.bounds.1, %within.bounds.2
1063 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1065 %i.i64 = zext i32 %i to i64
1066 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1067 %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1068 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1070 %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1071 %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1072 %loop.acc.next = add i32 %loop.acc.1, %array.2.i
1074 %i.next = add nuw i32 %i, 1
1075 %continue = icmp ult i32 %i.next, %n
1076 br i1 %continue, label %loop, label %exit
1079 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1083 define i32 @three_range_checks(ptr %array.1, i32 %length.1,
1084 ; CHECK-LABEL: @three_range_checks(
1085 ; CHECK-NEXT: entry:
1086 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1087 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1088 ; CHECK: loop.preheader:
1089 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1090 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1091 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1092 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1093 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1094 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1095 ; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1096 ; CHECK-NEXT: [[TMP7:%.*]] = freeze i1 [[TMP6]]
1097 ; CHECK-NEXT: [[TMP8:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1098 ; CHECK-NEXT: [[TMP9:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1099 ; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1100 ; CHECK-NEXT: [[TMP11:%.*]] = freeze i1 [[TMP10]]
1101 ; CHECK-NEXT: [[TMP12:%.*]] = and i1 [[TMP3]], [[TMP7]]
1102 ; CHECK-NEXT: [[TMP13:%.*]] = and i1 [[TMP12]], [[TMP11]]
1103 ; CHECK-NEXT: br label [[LOOP:%.*]]
1105 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1106 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1107 ; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1108 ; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1109 ; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]]
1110 ; CHECK-NEXT: [[WITHIN_BOUNDS_1_AND_2:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]]
1111 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1_AND_2]], [[WITHIN_BOUNDS_3]]
1112 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP13]], i32 9) [ "deopt"() ]
1113 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1114 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1115 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1116 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1117 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1118 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1119 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1120 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1121 ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]]
1122 ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4
1123 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1124 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1125 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1126 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1127 ; CHECK: exit.loopexit:
1128 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1129 ; CHECK-NEXT: br label [[EXIT]]
1131 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1132 ; CHECK-NEXT: ret i32 [[RESULT]]
1134 ptr %array.2, i32 %length.2,
1135 ptr %array.3, i32 %length.3, i32 %n) {
1137 %tmp5 = icmp eq i32 %n, 0
1138 br i1 %tmp5, label %exit, label %loop.preheader
1144 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1145 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1146 %within.bounds.1 = icmp ult i32 %i, %length.1
1147 %within.bounds.2 = icmp ult i32 %i, %length.2
1148 %within.bounds.3 = icmp ult i32 %i, %length.3
1149 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
1150 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
1151 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1153 %i.i64 = zext i32 %i to i64
1154 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1155 %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1156 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1158 %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1159 %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1160 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1162 %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64
1163 %array.3.i = load i32, ptr %array.3.i.ptr, align 4
1164 %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1166 %i.next = add nuw i32 %i, 1
1167 %continue = icmp ult i32 %i.next, %n
1168 br i1 %continue, label %loop, label %exit
1171 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1175 define i32 @three_guards(ptr %array.1, i32 %length.1,
1176 ; CHECK-LABEL: @three_guards(
1177 ; CHECK-NEXT: entry:
1178 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1179 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1180 ; CHECK: loop.preheader:
1181 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1182 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1183 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1184 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1185 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1186 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1187 ; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1188 ; CHECK-NEXT: [[TMP7:%.*]] = freeze i1 [[TMP6]]
1189 ; CHECK-NEXT: [[TMP8:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1190 ; CHECK-NEXT: [[TMP9:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1191 ; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1192 ; CHECK-NEXT: [[TMP11:%.*]] = freeze i1 [[TMP10]]
1193 ; CHECK-NEXT: br label [[LOOP:%.*]]
1195 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1196 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1197 ; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1198 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1199 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_1]])
1200 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1201 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1202 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1203 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1204 ; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1205 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP7]], i32 9) [ "deopt"() ]
1206 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_2]])
1207 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1208 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1209 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1210 ; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]]
1211 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP11]], i32 9) [ "deopt"() ]
1212 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_3]])
1213 ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]]
1214 ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4
1215 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1216 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1217 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1218 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1219 ; CHECK: exit.loopexit:
1220 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1221 ; CHECK-NEXT: br label [[EXIT]]
1223 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1224 ; CHECK-NEXT: ret i32 [[RESULT]]
1226 ptr %array.2, i32 %length.2,
1227 ptr %array.3, i32 %length.3, i32 %n) {
1229 %tmp5 = icmp eq i32 %n, 0
1230 br i1 %tmp5, label %exit, label %loop.preheader
1237 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1238 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1240 %within.bounds.1 = icmp ult i32 %i, %length.1
1241 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
1243 %i.i64 = zext i32 %i to i64
1244 %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1245 %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1246 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1248 %within.bounds.2 = icmp ult i32 %i, %length.2
1249 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
1251 %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1252 %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1253 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1255 %within.bounds.3 = icmp ult i32 %i, %length.3
1256 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
1258 %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64
1259 %array.3.i = load i32, ptr %array.3.i.ptr, align 4
1260 %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1262 %i.next = add nuw i32 %i, 1
1263 %continue = icmp ult i32 %i.next, %n
1264 br i1 %continue, label %loop, label %exit
1267 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1271 define i32 @unsigned_loop_0_to_n_unrelated_condition(ptr %array, i32 %length, i32 %n, i32 %x) {
1272 ; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition(
1273 ; CHECK-NEXT: entry:
1274 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1275 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1276 ; CHECK: loop.preheader:
1277 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
1278 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1279 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1280 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1281 ; CHECK-NEXT: br label [[LOOP:%.*]]
1283 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1284 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1285 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1286 ; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
1287 ; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[UNRELATED_COND]]
1288 ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[UNRELATED_COND]], [[TMP3]]
1289 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
1290 ; CHECK-NEXT: call void @llvm.assume(i1 [[GUARD_COND]])
1291 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1292 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1293 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1294 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1295 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1296 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1297 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1298 ; CHECK: exit.loopexit:
1299 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1300 ; CHECK-NEXT: br label [[EXIT]]
1302 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1303 ; CHECK-NEXT: ret i32 [[RESULT]]
1306 %tmp5 = icmp eq i32 %n, 0
1307 br i1 %tmp5, label %exit, label %loop.preheader
1313 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1314 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1315 %within.bounds = icmp ult i32 %i, %length
1316 %unrelated.cond = icmp ult i32 %x, %length
1317 %guard.cond = and i1 %within.bounds, %unrelated.cond
1318 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1320 %i.i64 = zext i32 %i to i64
1321 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1322 %array.i = load i32, ptr %array.i.ptr, align 4
1323 %loop.acc.next = add i32 %loop.acc, %array.i
1325 %i.next = add nuw i32 %i, 1
1326 %continue = icmp ult i32 %i.next, %n
1327 br i1 %continue, label %loop, label %exit
1330 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1334 ; Don't change the guard condition if there were no widened subconditions
1335 define i32 @test_no_widened_conditions(ptr %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
1336 ; CHECK-LABEL: @test_no_widened_conditions(
1337 ; CHECK-NEXT: entry:
1338 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1339 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1340 ; CHECK: loop.preheader:
1341 ; CHECK-NEXT: br label [[LOOP:%.*]]
1343 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1344 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1345 ; CHECK-NEXT: [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]]
1346 ; CHECK-NEXT: [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]]
1347 ; CHECK-NEXT: [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]]
1348 ; CHECK-NEXT: [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]]
1349 ; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]]
1350 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1351 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1352 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1353 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1354 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1355 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1356 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1357 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1358 ; CHECK: exit.loopexit:
1359 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1360 ; CHECK-NEXT: br label [[EXIT]]
1362 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1363 ; CHECK-NEXT: ret i32 [[RESULT]]
1366 %tmp5 = icmp eq i32 %n, 0
1367 br i1 %tmp5, label %exit, label %loop.preheader
1373 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1374 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1375 %unrelated.cond.1 = icmp eq i32 %x1, %i
1376 %unrelated.cond.2 = icmp eq i32 %x2, %i
1377 %unrelated.cond.3 = icmp eq i32 %x3, %i
1378 %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
1379 %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
1381 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1383 %i.i64 = zext i32 %i to i64
1384 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1385 %array.i = load i32, ptr %array.i.ptr, align 4
1386 %loop.acc.next = add i32 %loop.acc, %array.i
1388 %i.next = add nuw i32 %i, 1
1389 %continue = icmp ult i32 %i.next, %n
1390 br i1 %continue, label %loop, label %exit
1393 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1397 define i32 @signed_loop_start_to_n_loop_variant_bound(ptr %array, i32 %x, i32 %start, i32 %n) {
1398 ; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound(
1399 ; CHECK-NEXT: entry:
1400 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1401 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1402 ; CHECK: loop.preheader:
1403 ; CHECK-NEXT: br label [[LOOP:%.*]]
1405 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1406 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1407 ; CHECK-NEXT: [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]]
1408 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]]
1409 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1410 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1411 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1412 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1413 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1414 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
1415 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1416 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1417 ; CHECK: exit.loopexit:
1418 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1419 ; CHECK-NEXT: br label [[EXIT]]
1421 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1422 ; CHECK-NEXT: ret i32 [[RESULT]]
1425 %tmp5 = icmp sle i32 %n, 0
1426 br i1 %tmp5, label %exit, label %loop.preheader
1432 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1433 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1434 %bound = add i32 %i, %x
1435 %within.bounds = icmp ult i32 %i, %bound
1436 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1438 %i.i64 = zext i32 %i to i64
1439 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1440 %array.i = load i32, ptr %array.i.ptr, align 4
1441 %loop.acc.next = add i32 %loop.acc, %array.i
1443 %i.next = add nsw i32 %i, 1
1444 %continue = icmp slt i32 %i.next, %n
1445 br i1 %continue, label %loop, label %exit
1448 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1452 define i32 @signed_loop_start_to_n_non_monotonic_predicate(ptr %array, i32 %x, i32 %start, i32 %n) {
1453 ; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate(
1454 ; CHECK-NEXT: entry:
1455 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1456 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1457 ; CHECK: loop.preheader:
1458 ; CHECK-NEXT: br label [[LOOP:%.*]]
1460 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1461 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1462 ; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]]
1463 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1464 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1465 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1466 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1467 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1468 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
1469 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1470 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1471 ; CHECK: exit.loopexit:
1472 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1473 ; CHECK-NEXT: br label [[EXIT]]
1475 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1476 ; CHECK-NEXT: ret i32 [[RESULT]]
1479 %tmp5 = icmp sle i32 %n, 0
1480 br i1 %tmp5, label %exit, label %loop.preheader
1486 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1487 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1488 %guard.cond = icmp eq i32 %i, %x
1489 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1491 %i.i64 = zext i32 %i to i64
1492 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1493 %array.i = load i32, ptr %array.i.ptr, align 4
1494 %loop.acc.next = add i32 %loop.acc, %array.i
1496 %i.next = add nsw i32 %i, 1
1497 %continue = icmp slt i32 %i.next, %n
1498 br i1 %continue, label %loop, label %exit
1501 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1505 define i32 @unsigned_loop_0_to_n_hoist_length(ptr %array, i16 %length.i16, i32 %n) {
1506 ; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length(
1507 ; CHECK-NEXT: entry:
1508 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1509 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1510 ; CHECK: loop.preheader:
1511 ; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32
1512 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1513 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]]
1514 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1515 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
1516 ; CHECK-NEXT: br label [[LOOP:%.*]]
1518 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1519 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1520 ; CHECK-NEXT: [[LENGTH:%.*]] = zext i16 [[LENGTH_I16]] to i32
1521 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1522 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
1523 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1524 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1525 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1526 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1527 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1528 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1529 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1530 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1531 ; CHECK: exit.loopexit:
1532 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1533 ; CHECK-NEXT: br label [[EXIT]]
1535 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1536 ; CHECK-NEXT: ret i32 [[RESULT]]
1539 %tmp5 = icmp eq i32 %n, 0
1540 br i1 %tmp5, label %exit, label %loop.preheader
1546 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1547 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1548 %length = zext i16 %length.i16 to i32
1549 %within.bounds = icmp ult i32 %i, %length
1550 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1552 %i.i64 = zext i32 %i to i64
1553 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1554 %array.i = load i32, ptr %array.i.ptr, align 4
1555 %loop.acc.next = add i32 %loop.acc, %array.i
1557 %i.next = add nuw i32 %i, 1
1558 %continue = icmp ult i32 %i.next, %n
1559 br i1 %continue, label %loop, label %exit
1562 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1566 define i32 @unsigned_loop_0_to_n_cant_hoist_length(ptr %array, i32 %length, i32 %divider, i32 %n) {
1567 ; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length(
1568 ; CHECK-NEXT: entry:
1569 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1570 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1571 ; CHECK: loop.preheader:
1572 ; CHECK-NEXT: br label [[LOOP:%.*]]
1574 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1575 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1576 ; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]]
1577 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH_UDIV]]
1578 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]]
1579 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]]
1580 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1581 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1582 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1583 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1584 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1585 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1586 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1587 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1588 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1589 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1590 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1591 ; CHECK: exit.loopexit:
1592 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1593 ; CHECK-NEXT: br label [[EXIT]]
1595 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1596 ; CHECK-NEXT: ret i32 [[RESULT]]
1599 %tmp5 = icmp eq i32 %n, 0
1600 br i1 %tmp5, label %exit, label %loop.preheader
1606 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1607 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1608 %length.udiv = udiv i32 %length, %divider
1609 %within.bounds = icmp ult i32 %i, %length.udiv
1610 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1612 %i.i64 = zext i32 %i to i64
1613 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1614 %array.i = load i32, ptr %array.i.ptr, align 4
1615 %loop.acc.next = add i32 %loop.acc, %array.i
1617 %i.next = add nuw i32 %i, 1
1618 %continue = icmp ult i32 %i.next, %n
1619 br i1 %continue, label %loop, label %exit
1622 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1627 ; This is a case where the length information tells us that the guard
1628 ; must trigger on some iteration.
1629 define i32 @provably_taken(ptr %array, ptr %length.ptr) {
1630 ; CHECK-LABEL: @provably_taken(
1631 ; CHECK-NEXT: loop.preheader:
1632 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_PTR:%.*]], align 4, !range [[RNG1:![0-9]+]]
1633 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]]
1634 ; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], false
1635 ; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
1636 ; CHECK-NEXT: br label [[LOOP:%.*]]
1638 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1639 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1640 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1641 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1642 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1643 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1644 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1645 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1646 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1647 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1648 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200
1649 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1651 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1652 ; CHECK-NEXT: ret i32 [[RESULT]]
1655 %length = load i32, ptr %length.ptr, !range !{i32 0, i32 50}
1659 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1660 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1661 %within.bounds = icmp ult i32 %i, %length
1662 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1664 %i.i64 = zext i32 %i to i64
1665 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1666 %array.i = load i32, ptr %array.i.ptr, align 4
1667 %loop.acc.next = add i32 %loop.acc, %array.i
1669 %i.next = add nuw i32 %i, 1
1670 %continue = icmp slt i32 %i.next, 200
1671 br i1 %continue, label %loop, label %exit
1674 %result = phi i32 [ %loop.acc.next, %loop ]
1678 ; NE Check (as produced by LFTR) where we can prove Start < End via simple
1679 ; instruction analysis
1680 define i32 @ne_latch_zext(ptr %array, i32 %length, i16 %n16) {
1681 ; CHECK-LABEL: @ne_latch_zext(
1682 ; CHECK-NEXT: loop.preheader:
1683 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1684 ; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw nsw i32 [[N]], 1
1685 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[NPLUS1]], [[LENGTH:%.*]]
1686 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1687 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1688 ; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]
1689 ; CHECK-NEXT: br label [[LOOP:%.*]]
1691 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1692 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1693 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1694 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1695 ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1696 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1697 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1699 ; CHECK-NEXT: ret i32 0
1702 %n = zext i16 %n16 to i32
1703 %nplus1 = add nsw nuw i32 %n, 1
1707 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1708 %within.bounds = icmp ult i32 %i, %length
1709 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1711 %i.next = add nsw nuw i32 %i, 1
1712 %continue = icmp ne i32 %i.next, %nplus1
1713 br i1 %continue, label %loop, label %exit
1719 ; Same as previous, but with a pre-increment test since this is easier to match
1720 define i32 @ne_latch_zext_preinc(ptr %array, i32 %length, i16 %n16) {
1721 ; CHECK-LABEL: @ne_latch_zext_preinc(
1722 ; CHECK-NEXT: loop.preheader:
1723 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1724 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1725 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1726 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1727 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1728 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
1729 ; CHECK-NEXT: br label [[LOOP:%.*]]
1731 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1732 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1733 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
1734 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1735 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1736 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1737 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1739 ; CHECK-NEXT: ret i32 0
1742 %n = zext i16 %n16 to i32
1746 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1747 %within.bounds = icmp ult i32 %i, %length
1748 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1750 %i.next = add nuw i32 %i, 1
1751 %continue = icmp ne i32 %i, %n
1752 br i1 %continue, label %loop, label %exit
1758 ; NE Check (as produced by LFTR) where we can prove Start < End via the
1759 ; condition guarding the loop entry.
1760 define i32 @ne_latch_dom_check(ptr %array, i32 %length, i32 %n) {
1761 ; CHECK-LABEL: @ne_latch_dom_check(
1762 ; CHECK-NEXT: entry:
1763 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1764 ; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw i32 [[N]], 1
1765 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1766 ; CHECK: loop.preheader:
1767 ; CHECK-NEXT: br label [[LOOP:%.*]]
1769 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1770 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1771 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1772 ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1773 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1774 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1775 ; CHECK: exit.loopexit:
1776 ; CHECK-NEXT: br label [[EXIT]]
1778 ; CHECK-NEXT: ret i32 0
1781 %tmp5 = icmp sle i32 %n, 0
1782 %nplus1 = add nuw i32 %n, 1
1783 br i1 %tmp5, label %exit, label %loop.preheader
1789 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1790 %within.bounds = icmp ult i32 %i, %length
1791 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1793 %i.next = add nsw nuw i32 %i, 1
1794 %continue = icmp ne i32 %i.next, %nplus1
1795 br i1 %continue, label %loop, label %exit
1801 ; Same as previous, but easier to match
1802 define i32 @ne_latch_dom_check_preinc(ptr %array, i32 %length, i32 %n) {
1803 ; CHECK-LABEL: @ne_latch_dom_check_preinc(
1804 ; CHECK-NEXT: entry:
1805 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1806 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1807 ; CHECK: loop.preheader:
1808 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1809 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1810 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1811 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1812 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
1813 ; CHECK-NEXT: br label [[LOOP:%.*]]
1815 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1816 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1817 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
1818 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1819 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1820 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1821 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1822 ; CHECK: exit.loopexit:
1823 ; CHECK-NEXT: br label [[EXIT]]
1825 ; CHECK-NEXT: ret i32 0
1828 %tmp5 = icmp sle i32 %n, 0
1829 br i1 %tmp5, label %exit, label %loop.preheader
1835 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1836 %within.bounds = icmp ult i32 %i, %length
1837 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1839 %i.next = add nuw i32 %i, 1
1840 %continue = icmp ne i32 %i, %n
1841 br i1 %continue, label %loop, label %exit
1847 ; Same as previous, except swapped br/cmp
1848 define i32 @eq_latch_dom_check_preinc(ptr %array, i32 %length, i32 %n) {
1849 ; CHECK-LABEL: @eq_latch_dom_check_preinc(
1850 ; CHECK-NEXT: entry:
1851 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1852 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1853 ; CHECK: loop.preheader:
1854 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1855 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1856 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1857 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1858 ; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]]
1859 ; CHECK-NEXT: br label [[LOOP:%.*]]
1861 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1862 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1863 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
1864 ; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1865 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1866 ; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[I]], [[N]]
1867 ; CHECK-NEXT: br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
1868 ; CHECK: exit.loopexit:
1869 ; CHECK-NEXT: br label [[EXIT]]
1871 ; CHECK-NEXT: ret i32 0
1874 %tmp5 = icmp sle i32 %n, 0
1875 br i1 %tmp5, label %exit, label %loop.preheader
1881 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1882 %within.bounds = icmp ult i32 %i, %length
1883 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1885 %i.next = add nuw i32 %i, 1
1886 %done = icmp eq i32 %i, %n
1887 br i1 %done, label %exit, label %loop
1894 ; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap
1895 ; around several times or even be infinite)
1896 define i32 @neg_ne_latch_mod_step(ptr %array, i32 %length, i16 %n16) {
1897 ; CHECK-LABEL: @neg_ne_latch_mod_step(
1898 ; CHECK-NEXT: loop.preheader:
1899 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1900 ; CHECK-NEXT: br label [[LOOP:%.*]]
1902 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1903 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1904 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1905 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 3
1906 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1907 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1909 ; CHECK-NEXT: ret i32 0
1912 %n = zext i16 %n16 to i32
1916 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1917 %within.bounds = icmp ult i32 %i, %length
1918 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1920 %i.next = add i32 %i, 3
1921 %continue = icmp ne i32 %i, %n
1922 br i1 %continue, label %loop, label %exit
1928 ; NE latch - TODO: could prove (end-start) mod step == 0
1929 define i32 @ne_latch_mod_step(ptr %array, i32 %length) {
1930 ; CHECK-LABEL: @ne_latch_mod_step(
1931 ; CHECK-NEXT: loop.preheader:
1932 ; CHECK-NEXT: br label [[LOOP:%.*]]
1934 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1935 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1936 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1937 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 2
1938 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 400
1939 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1941 ; CHECK-NEXT: ret i32 0
1947 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1948 %within.bounds = icmp ult i32 %i, %length
1949 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1951 %i.next = add nuw i32 %i, 2
1952 %continue = icmp ne i32 %i, 400
1953 br i1 %continue, label %loop, label %exit
1959 ; NE Latch - but end > start so wraps around and not equivelent to a ult
1960 define i32 @neg_ne_latch_swapped_order(ptr %array, i32 %length) {
1961 ; CHECK-LABEL: @neg_ne_latch_swapped_order(
1962 ; CHECK-NEXT: loop.preheader:
1963 ; CHECK-NEXT: br label [[LOOP:%.*]]
1965 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1966 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1967 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1968 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
1969 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 0
1970 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1972 ; CHECK-NEXT: ret i32 0
1978 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
1979 %within.bounds = icmp ult i32 %i, %length
1980 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1982 %i.next = add i32 %i, 1
1983 %continue = icmp ne i32 %i, 0
1984 br i1 %continue, label %loop, label %exit
1990 ; Negative test, make sure we don't crash on unconditional latches
1991 ; TODO: there's no reason we shouldn't be able to predicate the
1992 ; condition for an statically infinite loop.
1993 define i32 @unconditional_latch(ptr %a, i32 %length) {
1994 ; CHECK-LABEL: @unconditional_latch(
1995 ; CHECK-NEXT: loop.preheader:
1996 ; CHECK-NEXT: br label [[LOOP:%.*]]
1998 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1999 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
2000 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
2001 ; CHECK-NEXT: store volatile i32 0, ptr [[A:%.*]], align 4
2002 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
2003 ; CHECK-NEXT: br label [[LOOP]]
2009 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
2010 %within.bounds = icmp ult i32 %i, %length
2011 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
2012 store volatile i32 0, ptr %a
2013 %i.next = add i32 %i, 1