xref: /llvm-project/llvm/test/Transforms/LoopPredication/basic.ll (revision ffb2af3ed6a95a4eb55b81a3d1351d5d4bd66eb5)
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
4
5declare void @llvm.experimental.guard(i1, ...)
6
7define 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]]
37;
38entry:
39  %tmp5 = icmp eq i32 %n, 0
40  br i1 %tmp5, label %exit, label %loop.preheader
41
42loop.preheader:
43  br label %loop
44
45loop:
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"() ]
50
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
55
56  %i.next = add nuw i32 %i, 1
57  %continue = icmp ult i32 %i.next, %n
58  br i1 %continue, label %loop, label %exit
59
60exit:
61  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
62  ret i32 %result
63}
64
65define 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]]
95;
96entry:
97  %tmp5 = icmp eq i32 %n, 0
98  br i1 %tmp5, label %exit, label %loop.preheader
99
100loop.preheader:
101  br label %loop
102
103loop:
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"() ]
108
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
113
114  %i.next = add nuw i32 %i, 1
115  %continue = icmp ule i32 %i.next, %n
116  br i1 %continue, label %loop, label %exit
117
118exit:
119  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
120  ret i32 %result
121}
122
123define 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]]
153;
154entry:
155  %tmp5 = icmp eq i32 %n, 0
156  br i1 %tmp5, label %exit, label %loop.preheader
157
158loop.preheader:
159  br label %loop
160
161loop:
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"() ]
166
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
171
172  %i.next = add nuw i32 %i, 1
173  %continue = icmp ult i32 %i.next, %n
174  br i1 %continue, label %loop, label %exit
175
176exit:
177  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
178  ret i32 %result
179}
180
181define 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]]
211;
212entry:
213  %tmp5 = icmp sle i32 %n, 0
214  br i1 %tmp5, label %exit, label %loop.preheader
215
216loop.preheader:
217  br label %loop
218
219loop:
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"() ]
224
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
229
230  %i.next = add nuw i32 %i, 1
231  %continue = icmp slt i32 %i.next, %n
232  br i1 %continue, label %loop, label %exit
233
234exit:
235  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
236  ret i32 %result
237}
238
239define 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]]
269;
270entry:
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
274
275loop.preheader:
276  br label %loop
277
278loop:
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"() ]
283
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
288
289  %i.next = add nuw i32 %i, 1
290  %continue = icmp slt i32 %i.next, %n
291  br i1 %continue, label %loop, label %exit
292
293exit:
294  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
295  ret i32 %result
296}
297
298define 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]]
328;
329entry:
330  %tmp5 = icmp sle i32 %n, 0
331  br i1 %tmp5, label %exit, label %loop.preheader
332
333loop.preheader:
334  br label %loop
335
336loop:
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"() ]
341
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
346
347  %i.next = add nuw i32 %i, 1
348  %continue = icmp sgt i32 %i.next, %n
349  br i1 %continue, label %exit, label %loop
350
351exit:
352  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
353  ret i32 %result
354}
355
356define 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]]
386;
387entry:
388  %tmp5 = icmp sle i32 %n, 0
389  br i1 %tmp5, label %exit, label %loop.preheader
390
391loop.preheader:
392  br label %loop
393
394loop:
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"() ]
399
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
404
405  %i.next = add nuw i32 %i, 1
406  %continue = icmp sle i32 %i.next, %n
407  br i1 %continue, label %loop, label %exit
408
409exit:
410  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
411  ret i32 %result
412}
413
414define 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]]
445;
446entry:
447  %tmp5 = icmp sle i32 %n, 0
448  br i1 %tmp5, label %exit, label %loop.preheader
449
450loop.preheader:
451  br label %loop
452
453loop:
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"() ]
458
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
463
464  %i.next = add i32 %i, 1
465  %continue = icmp slt i32 %i, %n
466  br i1 %continue, label %loop, label %exit
467
468exit:
469  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
470  ret i32 %result
471}
472
473define 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]]
504;
505entry:
506  %tmp5 = icmp sle i32 %n, 0
507  br i1 %tmp5, label %exit, label %loop.preheader
508
509loop.preheader:
510  br label %loop
511
512loop:
513  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
514  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
515
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"() ]
519
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
524
525  %continue = icmp slt i32 %i, %n
526  br i1 %continue, label %loop, label %exit
527
528exit:
529  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
530  ret i32 %result
531}
532
533define 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]]
565;
566entry:
567  %tmp5 = icmp sle i32 %n, 0
568  br i1 %tmp5, label %exit, label %loop.preheader
569
570loop.preheader:
571  br label %loop
572
573loop:
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"() ]
579
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
584
585  %i.next = add i32 %i, 1
586  %continue = icmp sle i32 %i.next, %n
587  br i1 %continue, label %loop, label %exit
588
589exit:
590  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
591  ret i32 %result
592}
593
594define 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]]
626;
627entry:
628  %tmp5 = icmp sle i32 %n, 0
629  br i1 %tmp5, label %exit, label %loop.preheader
630
631loop.preheader:
632  br label %loop
633
634loop:
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"() ]
640
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
645
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
650
651exit:
652  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
653  ret i32 %result
654}
655
656define 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]]
681;
682entry:
683  %tmp5 = icmp sle i32 %n, 0
684  br i1 %tmp5, label %exit, label %loop.preheader
685
686loop.preheader:
687  br label %loop
688
689loop:
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"() ]
694
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
699
700  %i.next = add nsw i32 %i, 1
701  %continue = icmp ne i32 %i.next, %n
702  br i1 %continue, label %loop, label %exit
703
704exit:
705  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
706  ret i32 %result
707}
708
709define 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]]
734;
735entry:
736  %tmp5 = icmp sle i32 %n, 0
737  br i1 %tmp5, label %exit, label %loop.preheader
738
739loop.preheader:
740  br label %loop
741
742loop:
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"() ]
747
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
752
753  %i.next = add nsw i32 %i, 2
754  %continue = icmp slt i32 %i.next, %n
755  br i1 %continue, label %loop, label %exit
756
757exit:
758  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
759  ret i32 %result
760}
761
762define 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]]
794;
795entry:
796  %tmp5 = icmp sle i32 %n, 0
797  br i1 %tmp5, label %exit, label %loop.preheader
798
799loop.preheader:
800  br label %loop
801
802loop:
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 ]
806
807  %within.bounds = icmp ult i32 %j, %length
808  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
809
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
814
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
819
820exit:
821  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
822  ret i32 %result
823}
824
825define 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]]
859;
860  i32 %start.j, i32 %length,
861  i32 %n) {
862entry:
863  %tmp5 = icmp sle i32 %n, 0
864  br i1 %tmp5, label %exit, label %loop.preheader
865
866loop.preheader:
867  br label %loop
868
869loop:
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 ]
873
874  %within.bounds = icmp ult i32 %j, %length
875  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
876
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
881
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
886
887exit:
888  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
889  ret i32 %result
890}
891
892define 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]]
919;
920entry:
921  %tmp5 = icmp sle i32 %n, 0
922  br i1 %tmp5, label %exit, label %loop.preheader
923
924loop.preheader:
925  br label %loop
926
927loop:
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 ]
931
932  %within.bounds = icmp ult i16 %j, %length
933  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
934
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
939
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
944
945exit:
946  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
947  ret i32 %result
948}
949
950define 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]]
977;
978entry:
979  %tmp5 = icmp sle i32 %n, 0
980  br i1 %tmp5, label %exit, label %loop.preheader
981
982loop.preheader:
983  br label %loop
984
985loop:
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 ]
989
990  %within.bounds = icmp ult i32 %j, %length
991  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
992
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
997
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
1002
1003exit:
1004  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1005  ret i32 %result
1006}
1007
1008define 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]]
1048;
1049  ptr %array.2, i32 %length.2, i32 %n) {
1050entry:
1051  %tmp5 = icmp eq i32 %n, 0
1052  br i1 %tmp5, label %exit, label %loop.preheader
1053
1054loop.preheader:
1055  br label %loop
1056
1057loop:
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"() ]
1064
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
1069
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
1073
1074  %i.next = add nuw i32 %i, 1
1075  %continue = icmp ult i32 %i.next, %n
1076  br i1 %continue, label %loop, label %exit
1077
1078exit:
1079  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1080  ret i32 %result
1081}
1082
1083define 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]]
1133;
1134  ptr %array.2, i32 %length.2,
1135  ptr %array.3, i32 %length.3, i32 %n) {
1136entry:
1137  %tmp5 = icmp eq i32 %n, 0
1138  br i1 %tmp5, label %exit, label %loop.preheader
1139
1140loop.preheader:
1141  br label %loop
1142
1143loop:
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"() ]
1152
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
1157
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
1161
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
1165
1166  %i.next = add nuw i32 %i, 1
1167  %continue = icmp ult i32 %i.next, %n
1168  br i1 %continue, label %loop, label %exit
1169
1170exit:
1171  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1172  ret i32 %result
1173}
1174
1175define 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]]
1225;
1226  ptr %array.2, i32 %length.2,
1227  ptr %array.3, i32 %length.3, i32 %n) {
1228entry:
1229  %tmp5 = icmp eq i32 %n, 0
1230  br i1 %tmp5, label %exit, label %loop.preheader
1231
1232loop.preheader:
1233  br label %loop
1234
1235loop:
1236
1237  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1238  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1239
1240  %within.bounds.1 = icmp ult i32 %i, %length.1
1241  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
1242
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
1247
1248  %within.bounds.2 = icmp ult i32 %i, %length.2
1249  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
1250
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
1254
1255  %within.bounds.3 = icmp ult i32 %i, %length.3
1256  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
1257
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
1261
1262  %i.next = add nuw i32 %i, 1
1263  %continue = icmp ult i32 %i.next, %n
1264  br i1 %continue, label %loop, label %exit
1265
1266exit:
1267  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1268  ret i32 %result
1269}
1270
1271define 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]]
1304;
1305entry:
1306  %tmp5 = icmp eq i32 %n, 0
1307  br i1 %tmp5, label %exit, label %loop.preheader
1308
1309loop.preheader:
1310  br label %loop
1311
1312loop:
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"() ]
1319
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
1324
1325  %i.next = add nuw i32 %i, 1
1326  %continue = icmp ult i32 %i.next, %n
1327  br i1 %continue, label %loop, label %exit
1328
1329exit:
1330  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1331  ret i32 %result
1332}
1333
1334; Don't change the guard condition if there were no widened subconditions
1335define 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]]
1364;
1365entry:
1366  %tmp5 = icmp eq i32 %n, 0
1367  br i1 %tmp5, label %exit, label %loop.preheader
1368
1369loop.preheader:
1370  br label %loop
1371
1372loop:
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
1380
1381  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1382
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
1387
1388  %i.next = add nuw i32 %i, 1
1389  %continue = icmp ult i32 %i.next, %n
1390  br i1 %continue, label %loop, label %exit
1391
1392exit:
1393  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1394  ret i32 %result
1395}
1396
1397define 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]]
1423;
1424entry:
1425  %tmp5 = icmp sle i32 %n, 0
1426  br i1 %tmp5, label %exit, label %loop.preheader
1427
1428loop.preheader:
1429  br label %loop
1430
1431loop:
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"() ]
1437
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
1442
1443  %i.next = add nsw i32 %i, 1
1444  %continue = icmp slt i32 %i.next, %n
1445  br i1 %continue, label %loop, label %exit
1446
1447exit:
1448  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1449  ret i32 %result
1450}
1451
1452define 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]]
1477;
1478entry:
1479  %tmp5 = icmp sle i32 %n, 0
1480  br i1 %tmp5, label %exit, label %loop.preheader
1481
1482loop.preheader:
1483  br label %loop
1484
1485loop:
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"() ]
1490
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
1495
1496  %i.next = add nsw i32 %i, 1
1497  %continue = icmp slt i32 %i.next, %n
1498  br i1 %continue, label %loop, label %exit
1499
1500exit:
1501  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1502  ret i32 %result
1503}
1504
1505define 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]]
1537;
1538entry:
1539  %tmp5 = icmp eq i32 %n, 0
1540  br i1 %tmp5, label %exit, label %loop.preheader
1541
1542loop.preheader:
1543  br label %loop
1544
1545loop:
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"() ]
1551
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
1556
1557  %i.next = add nuw i32 %i, 1
1558  %continue = icmp ult i32 %i.next, %n
1559  br i1 %continue, label %loop, label %exit
1560
1561exit:
1562  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1563  ret i32 %result
1564}
1565
1566define 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]]
1597;
1598entry:
1599  %tmp5 = icmp eq i32 %n, 0
1600  br i1 %tmp5, label %exit, label %loop.preheader
1601
1602loop.preheader:
1603  br label %loop
1604
1605loop:
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"() ]
1611
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
1616
1617  %i.next = add nuw i32 %i, 1
1618  %continue = icmp ult i32 %i.next, %n
1619  br i1 %continue, label %loop, label %exit
1620
1621exit:
1622  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1623  ret i32 %result
1624}
1625
1626
1627; This is a case where the length information tells us that the guard
1628; must trigger on some iteration.
1629define 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]]
1653;
1654loop.preheader:
1655  %length = load i32, ptr %length.ptr, !range !{i32 0, i32 50}
1656  br label %loop
1657
1658loop:
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"() ]
1663
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
1668
1669  %i.next = add nuw i32 %i, 1
1670  %continue = icmp slt i32 %i.next, 200
1671  br i1 %continue, label %loop, label %exit
1672
1673exit:
1674  %result = phi i32 [ %loop.acc.next, %loop ]
1675  ret i32 %result
1676}
1677
1678; NE Check (as produced by LFTR) where we can prove Start < End via simple
1679; instruction analysis
1680define 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
1700;
1701loop.preheader:
1702  %n = zext i16 %n16 to i32
1703  %nplus1 = add nsw nuw i32 %n, 1
1704  br label %loop
1705
1706loop:
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"() ]
1710
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
1714
1715exit:
1716  ret i32 0
1717}
1718
1719; Same as previous, but with a pre-increment test since this is easier to match
1720define 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
1740;
1741loop.preheader:
1742  %n = zext i16 %n16 to i32
1743  br label %loop
1744
1745loop:
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"() ]
1749
1750  %i.next = add nuw i32 %i, 1
1751  %continue = icmp ne i32 %i, %n
1752  br i1 %continue, label %loop, label %exit
1753
1754exit:
1755  ret i32 0
1756}
1757
1758; NE Check (as produced by LFTR) where we can prove Start < End via the
1759; condition guarding the loop entry.
1760define 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
1779;
1780entry:
1781  %tmp5 = icmp sle i32 %n, 0
1782  %nplus1 = add nuw i32 %n, 1
1783  br i1 %tmp5, label %exit, label %loop.preheader
1784
1785loop.preheader:
1786  br label %loop
1787
1788loop:
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"() ]
1792
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
1796
1797exit:
1798  ret i32 0
1799}
1800
1801; Same as previous, but easier to match
1802define 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
1826;
1827entry:
1828  %tmp5 = icmp sle i32 %n, 0
1829  br i1 %tmp5, label %exit, label %loop.preheader
1830
1831loop.preheader:
1832  br label %loop
1833
1834loop:
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"() ]
1838
1839  %i.next = add nuw i32 %i, 1
1840  %continue = icmp ne i32 %i, %n
1841  br i1 %continue, label %loop, label %exit
1842
1843exit:
1844  ret i32 0
1845}
1846
1847; Same as previous, except swapped br/cmp
1848define 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
1872;
1873entry:
1874  %tmp5 = icmp sle i32 %n, 0
1875  br i1 %tmp5, label %exit, label %loop.preheader
1876
1877loop.preheader:
1878  br label %loop
1879
1880loop:
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"() ]
1884
1885  %i.next = add nuw i32 %i, 1
1886  %done = icmp eq i32 %i, %n
1887  br i1 %done, label %exit, label %loop
1888
1889exit:
1890  ret i32 0
1891}
1892
1893
1894; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap
1895; around several times or even be infinite)
1896define 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
1910;
1911loop.preheader:
1912  %n = zext i16 %n16 to i32
1913  br label %loop
1914
1915loop:
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"() ]
1919
1920  %i.next = add i32 %i, 3
1921  %continue = icmp ne i32 %i, %n
1922  br i1 %continue, label %loop, label %exit
1923
1924exit:
1925  ret i32 0
1926}
1927
1928; NE latch - TODO: could prove (end-start) mod step == 0
1929define 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
1942;
1943loop.preheader:
1944  br label %loop
1945
1946loop:
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"() ]
1950
1951  %i.next = add nuw i32 %i, 2
1952  %continue = icmp ne i32 %i, 400
1953  br i1 %continue, label %loop, label %exit
1954
1955exit:
1956  ret i32 0
1957}
1958
1959; NE Latch - but end > start so wraps around and not equivelent to a ult
1960define 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
1973;
1974loop.preheader:
1975  br label %loop
1976
1977loop:
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"() ]
1981
1982  %i.next = add i32 %i, 1
1983  %continue = icmp ne i32 %i, 0
1984  br i1 %continue, label %loop, label %exit
1985
1986exit:
1987  ret i32 0
1988}
1989
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.
1993define 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]]
2004;
2005loop.preheader:
2006  br label %loop
2007
2008loop:
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
2015}
2016