Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopPredication / basic.ll
blob27c8bc99c407e0cbbd22cace6143faaf2b656b03
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(
9 ; CHECK-NEXT:  entry:
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:%.*]]
18 ; CHECK:       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]]
34 ; CHECK:       exit:
35 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
36 ; CHECK-NEXT:    ret i32 [[RESULT]]
38 entry:
39   %tmp5 = icmp eq i32 %n, 0
40   br i1 %tmp5, label %exit, label %loop.preheader
42 loop.preheader:
43   br label %loop
45 loop:
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
60 exit:
61   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
62   ret i32 %result
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(
67 ; CHECK-NEXT:  entry:
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:%.*]]
76 ; CHECK:       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]]
92 ; CHECK:       exit:
93 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
94 ; CHECK-NEXT:    ret i32 [[RESULT]]
96 entry:
97   %tmp5 = icmp eq i32 %n, 0
98   br i1 %tmp5, label %exit, label %loop.preheader
100 loop.preheader:
101   br label %loop
103 loop:
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
118 exit:
119   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
120   ret i32 %result
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(
125 ; CHECK-NEXT:  entry:
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:%.*]]
134 ; CHECK:       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]]
150 ; CHECK:       exit:
151 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
152 ; CHECK-NEXT:    ret i32 [[RESULT]]
154 entry:
155   %tmp5 = icmp eq i32 %n, 0
156   br i1 %tmp5, label %exit, label %loop.preheader
158 loop.preheader:
159   br label %loop
161 loop:
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
176 exit:
177   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
178   ret i32 %result
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(
183 ; CHECK-NEXT:  entry:
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:%.*]]
192 ; CHECK:       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]]
208 ; CHECK:       exit:
209 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
210 ; CHECK-NEXT:    ret i32 [[RESULT]]
212 entry:
213   %tmp5 = icmp sle i32 %n, 0
214   br i1 %tmp5, label %exit, label %loop.preheader
216 loop.preheader:
217   br label %loop
219 loop:
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
234 exit:
235   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
236   ret i32 %result
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(
241 ; CHECK-NEXT:  entry:
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:%.*]]
250 ; CHECK:       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]]
266 ; CHECK:       exit:
267 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
268 ; CHECK-NEXT:    ret i32 [[RESULT]]
270 entry:
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
275 loop.preheader:
276   br label %loop
278 loop:
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
293 exit:
294   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
295   ret i32 %result
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(
300 ; CHECK-NEXT:  entry:
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:%.*]]
309 ; CHECK:       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]]
325 ; CHECK:       exit:
326 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
327 ; CHECK-NEXT:    ret i32 [[RESULT]]
329 entry:
330   %tmp5 = icmp sle i32 %n, 0
331   br i1 %tmp5, label %exit, label %loop.preheader
333 loop.preheader:
334   br label %loop
336 loop:
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
351 exit:
352   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
353   ret i32 %result
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(
358 ; CHECK-NEXT:  entry:
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:%.*]]
367 ; CHECK:       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]]
383 ; CHECK:       exit:
384 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
385 ; CHECK-NEXT:    ret i32 [[RESULT]]
387 entry:
388   %tmp5 = icmp sle i32 %n, 0
389   br i1 %tmp5, label %exit, label %loop.preheader
391 loop.preheader:
392   br label %loop
394 loop:
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
409 exit:
410   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
411   ret i32 %result
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(
416 ; CHECK-NEXT:  entry:
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:%.*]]
426 ; CHECK:       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]]
442 ; CHECK:       exit:
443 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
444 ; CHECK-NEXT:    ret i32 [[RESULT]]
446 entry:
447   %tmp5 = icmp sle i32 %n, 0
448   br i1 %tmp5, label %exit, label %loop.preheader
450 loop.preheader:
451   br label %loop
453 loop:
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
468 exit:
469   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
470   ret i32 %result
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(
475 ; CHECK-NEXT:  entry:
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:%.*]]
485 ; CHECK:       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]]
501 ; CHECK:       exit:
502 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
503 ; CHECK-NEXT:    ret i32 [[RESULT]]
505 entry:
506   %tmp5 = icmp sle i32 %n, 0
507   br i1 %tmp5, label %exit, label %loop.preheader
509 loop.preheader:
510   br label %loop
512 loop:
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
528 exit:
529   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
530   ret i32 %result
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(
535 ; CHECK-NEXT:  entry:
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:%.*]]
545 ; CHECK:       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]]
562 ; CHECK:       exit:
563 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
564 ; CHECK-NEXT:    ret i32 [[RESULT]]
566 entry:
567   %tmp5 = icmp sle i32 %n, 0
568   br i1 %tmp5, label %exit, label %loop.preheader
570 loop.preheader:
571   br label %loop
573 loop:
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
589 exit:
590   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
591   ret i32 %result
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(
596 ; CHECK-NEXT:  entry:
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:%.*]]
605 ; CHECK:       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]]
623 ; CHECK:       exit:
624 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
625 ; CHECK-NEXT:    ret i32 [[RESULT]]
627 entry:
628   %tmp5 = icmp sle i32 %n, 0
629   br i1 %tmp5, label %exit, label %loop.preheader
631 loop.preheader:
632   br label %loop
634 loop:
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
651 exit:
652   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
653   ret i32 %result
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(
658 ; CHECK-NEXT:  entry:
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:%.*]]
663 ; CHECK:       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]]
678 ; CHECK:       exit:
679 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
680 ; CHECK-NEXT:    ret i32 [[RESULT]]
682 entry:
683   %tmp5 = icmp sle i32 %n, 0
684   br i1 %tmp5, label %exit, label %loop.preheader
686 loop.preheader:
687   br label %loop
689 loop:
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
704 exit:
705   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
706   ret i32 %result
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(
711 ; CHECK-NEXT:  entry:
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:%.*]]
716 ; CHECK:       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]]
731 ; CHECK:       exit:
732 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
733 ; CHECK-NEXT:    ret i32 [[RESULT]]
735 entry:
736   %tmp5 = icmp sle i32 %n, 0
737   br i1 %tmp5, label %exit, label %loop.preheader
739 loop.preheader:
740   br label %loop
742 loop:
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
757 exit:
758   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
759   ret i32 %result
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(
764 ; CHECK-NEXT:  entry:
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:%.*]]
773 ; CHECK:       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]]
791 ; CHECK:       exit:
792 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
793 ; CHECK-NEXT:    ret i32 [[RESULT]]
795 entry:
796   %tmp5 = icmp sle i32 %n, 0
797   br i1 %tmp5, label %exit, label %loop.preheader
799 loop.preheader:
800   br label %loop
802 loop:
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
820 exit:
821   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
822   ret i32 %result
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(
827 ; CHECK-NEXT:  entry:
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:%.*]]
838 ; CHECK:       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]]
856 ; CHECK:       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,
861   i32 %n) {
862 entry:
863   %tmp5 = icmp sle i32 %n, 0
864   br i1 %tmp5, label %exit, label %loop.preheader
866 loop.preheader:
867   br label %loop
869 loop:
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
887 exit:
888   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
889   ret i32 %result
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(
894 ; CHECK-NEXT:  entry:
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:%.*]]
899 ; CHECK:       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]]
916 ; CHECK:       exit:
917 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
918 ; CHECK-NEXT:    ret i32 [[RESULT]]
920 entry:
921   %tmp5 = icmp sle i32 %n, 0
922   br i1 %tmp5, label %exit, label %loop.preheader
924 loop.preheader:
925   br label %loop
927 loop:
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
945 exit:
946   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
947   ret i32 %result
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(
952 ; CHECK-NEXT:  entry:
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:%.*]]
957 ; CHECK:       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]]
974 ; CHECK:       exit:
975 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
976 ; CHECK-NEXT:    ret i32 [[RESULT]]
978 entry:
979   %tmp5 = icmp sle i32 %n, 0
980   br i1 %tmp5, label %exit, label %loop.preheader
982 loop.preheader:
983   br label %loop
985 loop:
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
1003 exit:
1004   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1005   ret i32 %result
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:%.*]]
1024 ; CHECK:       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]]
1045 ; CHECK:       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) {
1050 entry:
1051   %tmp5 = icmp eq i32 %n, 0
1052   br i1 %tmp5, label %exit, label %loop.preheader
1054 loop.preheader:
1055   br label %loop
1057 loop:
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
1078 exit:
1079   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1080   ret i32 %result
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:%.*]]
1104 ; CHECK:       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]]
1130 ; CHECK:       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) {
1136 entry:
1137   %tmp5 = icmp eq i32 %n, 0
1138   br i1 %tmp5, label %exit, label %loop.preheader
1140 loop.preheader:
1141   br label %loop
1143 loop:
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
1170 exit:
1171   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1172   ret i32 %result
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:%.*]]
1194 ; CHECK:       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]]
1222 ; CHECK:       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) {
1228 entry:
1229   %tmp5 = icmp eq i32 %n, 0
1230   br i1 %tmp5, label %exit, label %loop.preheader
1232 loop.preheader:
1233   br label %loop
1235 loop:
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
1266 exit:
1267   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1268   ret i32 %result
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:%.*]]
1282 ; CHECK:       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]]
1301 ; CHECK:       exit:
1302 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1303 ; CHECK-NEXT:    ret i32 [[RESULT]]
1305 entry:
1306   %tmp5 = icmp eq i32 %n, 0
1307   br i1 %tmp5, label %exit, label %loop.preheader
1309 loop.preheader:
1310   br label %loop
1312 loop:
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
1329 exit:
1330   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1331   ret i32 %result
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:%.*]]
1342 ; CHECK:       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]]
1361 ; CHECK:       exit:
1362 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1363 ; CHECK-NEXT:    ret i32 [[RESULT]]
1365 entry:
1366   %tmp5 = icmp eq i32 %n, 0
1367   br i1 %tmp5, label %exit, label %loop.preheader
1369 loop.preheader:
1370   br label %loop
1372 loop:
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
1392 exit:
1393   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1394   ret i32 %result
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:%.*]]
1404 ; CHECK:       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]]
1420 ; CHECK:       exit:
1421 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1422 ; CHECK-NEXT:    ret i32 [[RESULT]]
1424 entry:
1425   %tmp5 = icmp sle i32 %n, 0
1426   br i1 %tmp5, label %exit, label %loop.preheader
1428 loop.preheader:
1429   br label %loop
1431 loop:
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
1447 exit:
1448   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1449   ret i32 %result
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:%.*]]
1459 ; CHECK:       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]]
1474 ; CHECK:       exit:
1475 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1476 ; CHECK-NEXT:    ret i32 [[RESULT]]
1478 entry:
1479   %tmp5 = icmp sle i32 %n, 0
1480   br i1 %tmp5, label %exit, label %loop.preheader
1482 loop.preheader:
1483   br label %loop
1485 loop:
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
1500 exit:
1501   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1502   ret i32 %result
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:%.*]]
1517 ; CHECK:       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]]
1534 ; CHECK:       exit:
1535 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1536 ; CHECK-NEXT:    ret i32 [[RESULT]]
1538 entry:
1539   %tmp5 = icmp eq i32 %n, 0
1540   br i1 %tmp5, label %exit, label %loop.preheader
1542 loop.preheader:
1543   br label %loop
1545 loop:
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
1561 exit:
1562   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1563   ret i32 %result
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:%.*]]
1573 ; CHECK:       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]]
1594 ; CHECK:       exit:
1595 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1596 ; CHECK-NEXT:    ret i32 [[RESULT]]
1598 entry:
1599   %tmp5 = icmp eq i32 %n, 0
1600   br i1 %tmp5, label %exit, label %loop.preheader
1602 loop.preheader:
1603   br label %loop
1605 loop:
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
1621 exit:
1622   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1623   ret i32 %result
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:%.*]]
1637 ; CHECK:       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:%.*]]
1650 ; CHECK:       exit:
1651 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1652 ; CHECK-NEXT:    ret i32 [[RESULT]]
1654 loop.preheader:
1655   %length = load i32, ptr %length.ptr, !range !{i32 0, i32 50}
1656   br label %loop
1658 loop:
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
1673 exit:
1674   %result = phi i32 [ %loop.acc.next, %loop ]
1675   ret i32 %result
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:%.*]]
1690 ; CHECK:       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:%.*]]
1698 ; CHECK:       exit:
1699 ; CHECK-NEXT:    ret i32 0
1701 loop.preheader:
1702   %n = zext i16 %n16 to i32
1703   %nplus1 = add nsw nuw i32 %n, 1
1704   br label %loop
1706 loop:
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
1715 exit:
1716   ret i32 0
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:%.*]]
1730 ; CHECK:       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:%.*]]
1738 ; CHECK:       exit:
1739 ; CHECK-NEXT:    ret i32 0
1741 loop.preheader:
1742   %n = zext i16 %n16 to i32
1743   br label %loop
1745 loop:
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
1754 exit:
1755   ret i32 0
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:%.*]]
1768 ; CHECK:       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]]
1777 ; CHECK:       exit:
1778 ; CHECK-NEXT:    ret i32 0
1780 entry:
1781   %tmp5 = icmp sle i32 %n, 0
1782   %nplus1 = add nuw i32 %n, 1
1783   br i1 %tmp5, label %exit, label %loop.preheader
1785 loop.preheader:
1786   br label %loop
1788 loop:
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
1797 exit:
1798   ret i32 0
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:%.*]]
1814 ; CHECK:       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]]
1824 ; CHECK:       exit:
1825 ; CHECK-NEXT:    ret i32 0
1827 entry:
1828   %tmp5 = icmp sle i32 %n, 0
1829   br i1 %tmp5, label %exit, label %loop.preheader
1831 loop.preheader:
1832   br label %loop
1834 loop:
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
1843 exit:
1844   ret i32 0
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:%.*]]
1860 ; CHECK:       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]]
1870 ; CHECK:       exit:
1871 ; CHECK-NEXT:    ret i32 0
1873 entry:
1874   %tmp5 = icmp sle i32 %n, 0
1875   br i1 %tmp5, label %exit, label %loop.preheader
1877 loop.preheader:
1878   br label %loop
1880 loop:
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
1889 exit:
1890   ret i32 0
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:%.*]]
1901 ; CHECK:       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:%.*]]
1908 ; CHECK:       exit:
1909 ; CHECK-NEXT:    ret i32 0
1911 loop.preheader:
1912   %n = zext i16 %n16 to i32
1913   br label %loop
1915 loop:
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
1924 exit:
1925   ret i32 0
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:%.*]]
1933 ; CHECK:       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:%.*]]
1940 ; CHECK:       exit:
1941 ; CHECK-NEXT:    ret i32 0
1943 loop.preheader:
1944   br label %loop
1946 loop:
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
1955 exit:
1956   ret i32 0
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:%.*]]
1964 ; CHECK:       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:%.*]]
1971 ; CHECK:       exit:
1972 ; CHECK-NEXT:    ret i32 0
1974 loop.preheader:
1975   br label %loop
1977 loop:
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
1986 exit:
1987   ret i32 0
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:%.*]]
1997 ; CHECK:       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]]
2005 loop.preheader:
2006   br label %loop
2008 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
2014   br label %loop