1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -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(i32* %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:    br label [[LOOP:%.*]]
17; CHECK:       loop:
18; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
19; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
20; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
21; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
22; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
23; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
24; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
25; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
26; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
27; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
28; CHECK:       exit.loopexit:
29; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
30; CHECK-NEXT:    br label [[EXIT]]
31; CHECK:       exit:
32; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
33; CHECK-NEXT:    ret i32 [[RESULT]]
34;
35entry:
36  %tmp5 = icmp eq i32 %n, 0
37  br i1 %tmp5, label %exit, label %loop.preheader
38
39loop.preheader:
40  br label %loop
41
42loop:
43  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
44  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
45  %within.bounds = icmp ult i32 %i, %length
46  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
47
48  %i.i64 = zext i32 %i to i64
49  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
50  %array.i = load i32, i32* %array.i.ptr, align 4
51  %loop.acc.next = add i32 %loop.acc, %array.i
52
53  %i.next = add nuw i32 %i, 1
54  %continue = icmp ult i32 %i.next, %n
55  br i1 %continue, label %loop, label %exit
56
57exit:
58  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
59  ret i32 %result
60}
61
62define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) {
63; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check(
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
66; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
67; CHECK:       loop.preheader:
68; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]]
69; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
70; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
71; CHECK-NEXT:    br label [[LOOP:%.*]]
72; CHECK:       loop:
73; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
74; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
75; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
76; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
77; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
78; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
79; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
80; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
81; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]]
82; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
83; CHECK:       exit.loopexit:
84; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
85; CHECK-NEXT:    br label [[EXIT]]
86; CHECK:       exit:
87; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
88; CHECK-NEXT:    ret i32 [[RESULT]]
89;
90entry:
91  %tmp5 = icmp eq i32 %n, 0
92  br i1 %tmp5, label %exit, label %loop.preheader
93
94loop.preheader:
95  br label %loop
96
97loop:
98  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
99  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
100  %within.bounds = icmp ult i32 %i, %length
101  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
102
103  %i.i64 = zext i32 %i to i64
104  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
105  %array.i = load i32, i32* %array.i.ptr, align 4
106  %loop.acc.next = add i32 %loop.acc, %array.i
107
108  %i.next = add nuw i32 %i, 1
109  %continue = icmp ule i32 %i.next, %n
110  br i1 %continue, label %loop, label %exit
111
112exit:
113  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
114  ret i32 %result
115}
116
117define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) {
118; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check(
119; CHECK-NEXT:  entry:
120; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
121; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
122; CHECK:       loop.preheader:
123; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
124; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
125; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
126; CHECK-NEXT:    br label [[LOOP:%.*]]
127; CHECK:       loop:
128; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
129; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
130; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
131; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
132; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
133; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
134; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
135; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
136; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
137; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
138; CHECK:       exit.loopexit:
139; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
140; CHECK-NEXT:    br label [[EXIT]]
141; CHECK:       exit:
142; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
143; CHECK-NEXT:    ret i32 [[RESULT]]
144;
145entry:
146  %tmp5 = icmp eq i32 %n, 0
147  br i1 %tmp5, label %exit, label %loop.preheader
148
149loop.preheader:
150  br label %loop
151
152loop:
153  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
154  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
155  %within.bounds = icmp ugt i32 %length, %i
156  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
157
158  %i.i64 = zext i32 %i to i64
159  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
160  %array.i = load i32, i32* %array.i.ptr, align 4
161  %loop.acc.next = add i32 %loop.acc, %array.i
162
163  %i.next = add nuw i32 %i, 1
164  %continue = icmp ult i32 %i.next, %n
165  br i1 %continue, label %loop, label %exit
166
167exit:
168  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
169  ret i32 %result
170}
171
172define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
173; CHECK-LABEL: @signed_loop_0_to_n_ult_check(
174; CHECK-NEXT:  entry:
175; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
176; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
177; CHECK:       loop.preheader:
178; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
179; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
180; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
181; CHECK-NEXT:    br label [[LOOP:%.*]]
182; CHECK:       loop:
183; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
184; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
185; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
186; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
187; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
188; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
189; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
190; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
191; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
192; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
193; CHECK:       exit.loopexit:
194; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
195; CHECK-NEXT:    br label [[EXIT]]
196; CHECK:       exit:
197; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
198; CHECK-NEXT:    ret i32 [[RESULT]]
199;
200entry:
201  %tmp5 = icmp sle i32 %n, 0
202  br i1 %tmp5, label %exit, label %loop.preheader
203
204loop.preheader:
205  br label %loop
206
207loop:
208  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
209  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
210  %within.bounds = icmp ult i32 %i, %length
211  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
212
213  %i.i64 = zext i32 %i to i64
214  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
215  %array.i = load i32, i32* %array.i.ptr, align 4
216  %loop.acc.next = add i32 %loop.acc, %array.i
217
218  %i.next = add nuw i32 %i, 1
219  %continue = icmp slt i32 %i.next, %n
220  br i1 %continue, label %loop, label %exit
221
222exit:
223  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
224  ret i32 %result
225}
226
227define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) {
228; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known(
229; CHECK-NEXT:  entry:
230; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
231; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]]
232; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
233; CHECK:       loop.preheader:
234; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]]
235; CHECK-NEXT:    br label [[LOOP:%.*]]
236; CHECK:       loop:
237; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
238; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
239; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP0]], i32 9) [ "deopt"() ]
240; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
241; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
242; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
243; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
244; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
245; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
246; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
247; CHECK:       exit.loopexit:
248; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
249; CHECK-NEXT:    br label [[EXIT]]
250; CHECK:       exit:
251; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
252; CHECK-NEXT:    ret i32 [[RESULT]]
253;
254entry:
255  %tmp5 = icmp sle i32 %n, 0
256  %length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648}
257  br i1 %tmp5, label %exit, label %loop.preheader
258
259loop.preheader:
260  br label %loop
261
262loop:
263  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
264  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
265  %within.bounds = icmp ult i32 %i, %length
266  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
267
268  %i.i64 = zext i32 %i to i64
269  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
270  %array.i = load i32, i32* %array.i.ptr, align 4
271  %loop.acc.next = add i32 %loop.acc, %array.i
272
273  %i.next = add nuw i32 %i, 1
274  %continue = icmp slt i32 %i.next, %n
275  br i1 %continue, label %loop, label %exit
276
277exit:
278  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
279  ret i32 %result
280}
281
282define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) {
283; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate(
284; CHECK-NEXT:  entry:
285; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
286; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
287; CHECK:       loop.preheader:
288; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
289; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
290; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
291; CHECK-NEXT:    br label [[LOOP:%.*]]
292; CHECK:       loop:
293; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
294; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
295; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
296; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
297; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
298; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
299; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
300; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
301; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]]
302; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
303; CHECK:       exit.loopexit:
304; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
305; CHECK-NEXT:    br label [[EXIT]]
306; CHECK:       exit:
307; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
308; CHECK-NEXT:    ret i32 [[RESULT]]
309;
310entry:
311  %tmp5 = icmp sle i32 %n, 0
312  br i1 %tmp5, label %exit, label %loop.preheader
313
314loop.preheader:
315  br label %loop
316
317loop:
318  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
319  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
320  %within.bounds = icmp ult i32 %i, %length
321  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
322
323  %i.i64 = zext i32 %i to i64
324  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
325  %array.i = load i32, i32* %array.i.ptr, align 4
326  %loop.acc.next = add i32 %loop.acc, %array.i
327
328  %i.next = add nuw i32 %i, 1
329  %continue = icmp sgt i32 %i.next, %n
330  br i1 %continue, label %exit, label %loop
331
332exit:
333  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
334  ret i32 %result
335}
336
337define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) {
338; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check(
339; CHECK-NEXT:  entry:
340; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
341; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
342; CHECK:       loop.preheader:
343; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
344; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
345; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
346; CHECK-NEXT:    br label [[LOOP:%.*]]
347; CHECK:       loop:
348; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
349; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
350; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
351; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
352; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
353; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
354; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
355; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
356; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
357; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
358; CHECK:       exit.loopexit:
359; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
360; CHECK-NEXT:    br label [[EXIT]]
361; CHECK:       exit:
362; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
363; CHECK-NEXT:    ret i32 [[RESULT]]
364;
365entry:
366  %tmp5 = icmp sle i32 %n, 0
367  br i1 %tmp5, label %exit, label %loop.preheader
368
369loop.preheader:
370  br label %loop
371
372loop:
373  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
374  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
375  %within.bounds = icmp ult i32 %i, %length
376  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
377
378  %i.i64 = zext i32 %i to i64
379  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
380  %array.i = load i32, i32* %array.i.ptr, align 4
381  %loop.acc.next = add i32 %loop.acc, %array.i
382
383  %i.next = add nuw i32 %i, 1
384  %continue = icmp sle i32 %i.next, %n
385  br i1 %continue, label %loop, label %exit
386
387exit:
388  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
389  ret i32 %result
390}
391
392define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length, i32 %n) {
393; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check(
394; CHECK-NEXT:  entry:
395; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
396; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
397; CHECK:       loop.preheader:
398; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
399; CHECK-NEXT:    [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
400; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
401; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
402; CHECK-NEXT:    br label [[LOOP:%.*]]
403; CHECK:       loop:
404; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
405; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
406; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
407; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
408; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
409; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
410; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
411; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
412; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
413; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
414; CHECK:       exit.loopexit:
415; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
416; CHECK-NEXT:    br label [[EXIT]]
417; CHECK:       exit:
418; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
419; CHECK-NEXT:    ret i32 [[RESULT]]
420;
421entry:
422  %tmp5 = icmp sle i32 %n, 0
423  br i1 %tmp5, label %exit, label %loop.preheader
424
425loop.preheader:
426  br label %loop
427
428loop:
429  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
430  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
431  %within.bounds = icmp ult i32 %i, %length
432  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
433
434  %i.i64 = zext i32 %i to i64
435  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
436  %array.i = load i32, i32* %array.i.ptr, align 4
437  %loop.acc.next = add i32 %loop.acc, %array.i
438
439  %i.next = add i32 %i, 1
440  %continue = icmp slt i32 %i, %n
441  br i1 %continue, label %loop, label %exit
442
443exit:
444  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
445  ret i32 %result
446}
447
448define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(i32* %array, i32 %length, i32 %n) {
449; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(
450; CHECK-NEXT:  entry:
451; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
452; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
453; CHECK:       loop.preheader:
454; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2
455; CHECK-NEXT:    [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
456; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
457; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
458; CHECK-NEXT:    br label [[LOOP:%.*]]
459; CHECK:       loop:
460; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
461; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
462; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
463; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
464; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
465; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
466; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
467; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
468; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
469; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
470; CHECK:       exit.loopexit:
471; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
472; CHECK-NEXT:    br label [[EXIT]]
473; CHECK:       exit:
474; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
475; CHECK-NEXT:    ret i32 [[RESULT]]
476;
477entry:
478  %tmp5 = icmp sle i32 %n, 0
479  br i1 %tmp5, label %exit, label %loop.preheader
480
481loop.preheader:
482  br label %loop
483
484loop:
485  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
486  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
487
488  %i.next = add i32 %i, 1
489  %within.bounds = icmp ult i32 %i.next, %length
490  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
491
492  %i.i64 = zext i32 %i to i64
493  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
494  %array.i = load i32, i32* %array.i.ptr, align 4
495  %loop.acc.next = add i32 %loop.acc, %array.i
496
497  %continue = icmp slt i32 %i, %n
498  br i1 %continue, label %loop, label %exit
499
500exit:
501  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
502  ret i32 %result
503}
504
505define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
506; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check(
507; CHECK-NEXT:  entry:
508; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
509; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
510; CHECK:       loop.preheader:
511; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
512; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]]
513; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
514; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
515; CHECK-NEXT:    br label [[LOOP:%.*]]
516; CHECK:       loop:
517; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
518; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
519; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
520; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
521; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
522; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
523; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
524; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
525; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
526; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
527; CHECK:       exit.loopexit:
528; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
529; CHECK-NEXT:    br label [[EXIT]]
530; CHECK:       exit:
531; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
532; CHECK-NEXT:    ret i32 [[RESULT]]
533;
534entry:
535  %tmp5 = icmp sle i32 %n, 0
536  br i1 %tmp5, label %exit, label %loop.preheader
537
538loop.preheader:
539  br label %loop
540
541loop:
542  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
543  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
544  %i.offset = add i32 %i, 1
545  %within.bounds = icmp ult i32 %i.offset, %length
546  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
547
548  %i.i64 = zext i32 %i to i64
549  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
550  %array.i = load i32, i32* %array.i.ptr, align 4
551  %loop.acc.next = add i32 %loop.acc, %array.i
552
553  %i.next = add i32 %i, 1
554  %continue = icmp sle i32 %i.next, %n
555  br i1 %continue, label %loop, label %exit
556
557exit:
558  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
559  ret i32 %result
560}
561
562define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
563; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(
564; CHECK-NEXT:  entry:
565; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
566; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
567; CHECK:       loop.preheader:
568; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
569; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]]
570; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
571; CHECK-NEXT:    br label [[LOOP:%.*]]
572; CHECK:       loop:
573; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
574; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
575; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
576; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
577; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
578; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
579; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
580; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
581; CHECK-NEXT:    [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1
582; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]]
583; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
584; CHECK:       exit.loopexit:
585; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
586; CHECK-NEXT:    br label [[EXIT]]
587; CHECK:       exit:
588; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
589; CHECK-NEXT:    ret i32 [[RESULT]]
590;
591entry:
592  %tmp5 = icmp sle i32 %n, 0
593  br i1 %tmp5, label %exit, label %loop.preheader
594
595loop.preheader:
596  br label %loop
597
598loop:
599  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
600  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
601  %i.offset = add i32 %i, 1
602  %within.bounds = icmp ult i32 %i.offset, %length
603  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
604
605  %i.i64 = zext i32 %i to i64
606  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
607  %array.i = load i32, i32* %array.i.ptr, align 4
608  %loop.acc.next = add i32 %loop.acc, %array.i
609
610  %i.next = add i32 %i, 1
611  %i.next.offset = add i32 %i.next, 1
612  %continue = icmp sle i32 %i.next.offset, %n
613  br i1 %continue, label %loop, label %exit
614
615exit:
616  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
617  ret i32 %result
618}
619
620define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
621; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n(
622; CHECK-NEXT:  entry:
623; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
624; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
625; CHECK:       loop.preheader:
626; CHECK-NEXT:    br label [[LOOP:%.*]]
627; CHECK:       loop:
628; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
629; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
630; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
631; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
632; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
633; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
634; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
635; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
636; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
637; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
638; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
639; CHECK:       exit.loopexit:
640; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
641; CHECK-NEXT:    br label [[EXIT]]
642; CHECK:       exit:
643; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
644; CHECK-NEXT:    ret i32 [[RESULT]]
645;
646entry:
647  %tmp5 = icmp sle i32 %n, 0
648  br i1 %tmp5, label %exit, label %loop.preheader
649
650loop.preheader:
651  br label %loop
652
653loop:
654  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
655  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
656  %within.bounds = icmp ult i32 %i, %length
657  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
658
659  %i.i64 = zext i32 %i to i64
660  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
661  %array.i = load i32, i32* %array.i.ptr, align 4
662  %loop.acc.next = add i32 %loop.acc, %array.i
663
664  %i.next = add nsw i32 %i, 1
665  %continue = icmp ne i32 %i.next, %n
666  br i1 %continue, label %loop, label %exit
667
668exit:
669  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
670  ret i32 %result
671}
672
673define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
674; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step(
675; CHECK-NEXT:  entry:
676; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
677; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
678; CHECK:       loop.preheader:
679; CHECK-NEXT:    br label [[LOOP:%.*]]
680; CHECK:       loop:
681; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
682; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
683; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
684; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
685; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
686; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
687; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
688; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
689; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 2
690; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
691; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
692; CHECK:       exit.loopexit:
693; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
694; CHECK-NEXT:    br label [[EXIT]]
695; CHECK:       exit:
696; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
697; CHECK-NEXT:    ret i32 [[RESULT]]
698;
699entry:
700  %tmp5 = icmp sle i32 %n, 0
701  br i1 %tmp5, label %exit, label %loop.preheader
702
703loop.preheader:
704  br label %loop
705
706loop:
707  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
708  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
709  %within.bounds = icmp ult i32 %i, %length
710  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
711
712  %i.i64 = zext i32 %i to i64
713  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
714  %array.i = load i32, i32* %array.i.ptr, align 4
715  %loop.acc.next = add i32 %loop.acc, %array.i
716
717  %i.next = add nsw i32 %i, 2
718  %continue = icmp slt i32 %i.next, %n
719  br i1 %continue, label %loop, label %exit
720
721exit:
722  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
723  ret i32 %result
724}
725
726define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
727; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check(
728; CHECK-NEXT:  entry:
729; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
730; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
731; CHECK:       loop.preheader:
732; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
733; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
734; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
735; CHECK-NEXT:    br label [[LOOP:%.*]]
736; CHECK:       loop:
737; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
738; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
739; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
740; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
741; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
742; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
743; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
744; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
745; CHECK-NEXT:    [[J_NEXT]] = add nsw i32 [[J]], 1
746; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
747; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
748; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
749; CHECK:       exit.loopexit:
750; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
751; CHECK-NEXT:    br label [[EXIT]]
752; CHECK:       exit:
753; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
754; CHECK-NEXT:    ret i32 [[RESULT]]
755;
756entry:
757  %tmp5 = icmp sle i32 %n, 0
758  br i1 %tmp5, label %exit, label %loop.preheader
759
760loop.preheader:
761  br label %loop
762
763loop:
764  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
765  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
766  %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
767
768  %within.bounds = icmp ult i32 %j, %length
769  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
770
771  %i.i64 = zext i32 %i to i64
772  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
773  %array.i = load i32, i32* %array.i.ptr, align 4
774  %loop.acc.next = add i32 %loop.acc, %array.i
775
776  %j.next = add nsw i32 %j, 1
777  %i.next = add nsw i32 %i, 1
778  %continue = icmp slt i32 %i.next, %n
779  br i1 %continue, label %loop, label %exit
780
781exit:
782  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
783  ret i32 %result
784}
785
786define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start.i,
787; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check(
788; CHECK-NEXT:  entry:
789; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
790; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
791; CHECK:       loop.preheader:
792; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]]
793; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]]
794; CHECK-NEXT:    [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]]
795; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]]
796; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]]
797; CHECK-NEXT:    br label [[LOOP:%.*]]
798; CHECK:       loop:
799; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
800; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START_I]], [[LOOP_PREHEADER]] ]
801; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ]
802; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
803; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
804; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
805; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
806; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
807; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
808; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
809; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
810; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
811; CHECK:       exit.loopexit:
812; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
813; CHECK-NEXT:    br label [[EXIT]]
814; CHECK:       exit:
815; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
816; CHECK-NEXT:    ret i32 [[RESULT]]
817;
818  i32 %start.j, i32 %length,
819  i32 %n) {
820entry:
821  %tmp5 = icmp sle i32 %n, 0
822  br i1 %tmp5, label %exit, label %loop.preheader
823
824loop.preheader:
825  br label %loop
826
827loop:
828  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
829  %i = phi i32 [ %i.next, %loop ], [ %start.i, %loop.preheader ]
830  %j = phi i32 [ %j.next, %loop ], [ %start.j, %loop.preheader ]
831
832  %within.bounds = icmp ult i32 %j, %length
833  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
834
835  %i.i64 = zext i32 %i to i64
836  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
837  %array.i = load i32, i32* %array.i.ptr, align 4
838  %loop.acc.next = add i32 %loop.acc, %array.i
839
840  %j.next = add i32 %j, 1
841  %i.next = add i32 %i, 1
842  %continue = icmp slt i32 %i.next, %n
843  br i1 %continue, label %loop, label %exit
844
845exit:
846  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
847  ret i32 %result
848}
849
850define i32 @signed_loop_0_to_n_different_iv_types(i32* %array, i16 %length, i32 %n) {
851; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types(
852; CHECK-NEXT:  entry:
853; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
854; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
855; CHECK:       loop.preheader:
856; CHECK-NEXT:    br label [[LOOP:%.*]]
857; CHECK:       loop:
858; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
859; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
860; CHECK-NEXT:    [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
861; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]]
862; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
863; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
864; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
865; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
866; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
867; CHECK-NEXT:    [[J_NEXT]] = add i16 [[J]], 1
868; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
869; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
870; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
871; CHECK:       exit.loopexit:
872; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
873; CHECK-NEXT:    br label [[EXIT]]
874; CHECK:       exit:
875; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
876; CHECK-NEXT:    ret i32 [[RESULT]]
877;
878entry:
879  %tmp5 = icmp sle i32 %n, 0
880  br i1 %tmp5, label %exit, label %loop.preheader
881
882loop.preheader:
883  br label %loop
884
885loop:
886  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
887  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
888  %j = phi i16 [ %j.next, %loop ], [ 0, %loop.preheader ]
889
890  %within.bounds = icmp ult i16 %j, %length
891  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
892
893  %i.i64 = zext i32 %i to i64
894  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
895  %array.i = load i32, i32* %array.i.ptr, align 4
896  %loop.acc.next = add i32 %loop.acc, %array.i
897
898  %j.next = add i16 %j, 1
899  %i.next = add i32 %i, 1
900  %continue = icmp slt i32 %i.next, %n
901  br i1 %continue, label %loop, label %exit
902
903exit:
904  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
905  ret i32 %result
906}
907
908define i32 @signed_loop_0_to_n_different_iv_strides(i32* %array, i32 %length, i32 %n) {
909; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides(
910; CHECK-NEXT:  entry:
911; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
912; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
913; CHECK:       loop.preheader:
914; CHECK-NEXT:    br label [[LOOP:%.*]]
915; CHECK:       loop:
916; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
917; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
918; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
919; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]]
920; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
921; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
922; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
923; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
924; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
925; CHECK-NEXT:    [[J_NEXT]] = add nsw i32 [[J]], 2
926; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
927; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
928; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
929; CHECK:       exit.loopexit:
930; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
931; CHECK-NEXT:    br label [[EXIT]]
932; CHECK:       exit:
933; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
934; CHECK-NEXT:    ret i32 [[RESULT]]
935;
936entry:
937  %tmp5 = icmp sle i32 %n, 0
938  br i1 %tmp5, label %exit, label %loop.preheader
939
940loop.preheader:
941  br label %loop
942
943loop:
944  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
945  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
946  %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
947
948  %within.bounds = icmp ult i32 %j, %length
949  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
950
951  %i.i64 = zext i32 %i to i64
952  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
953  %array.i = load i32, i32* %array.i.ptr, align 4
954  %loop.acc.next = add i32 %loop.acc, %array.i
955
956  %j.next = add nsw i32 %j, 2
957  %i.next = add nsw i32 %i, 1
958  %continue = icmp slt i32 %i.next, %n
959  br i1 %continue, label %loop, label %exit
960
961exit:
962  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
963  ret i32 %result
964}
965
966define i32 @two_range_checks(i32* %array.1, i32 %length.1,
967; CHECK-LABEL: @two_range_checks(
968; CHECK-NEXT:  entry:
969; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
970; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
971; CHECK:       loop.preheader:
972; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
973; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]]
974; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
975; CHECK-NEXT:    [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
976; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_1]]
977; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
978; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP2]], [[TMP5]]
979; CHECK-NEXT:    br label [[LOOP:%.*]]
980; CHECK:       loop:
981; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
982; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
983; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ]
984; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
985; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
986; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
987; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
988; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
989; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
990; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
991; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
992; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
993; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
994; CHECK:       exit.loopexit:
995; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
996; CHECK-NEXT:    br label [[EXIT]]
997; CHECK:       exit:
998; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
999; CHECK-NEXT:    ret i32 [[RESULT]]
1000;
1001  i32* %array.2, i32 %length.2, i32 %n) {
1002entry:
1003  %tmp5 = icmp eq i32 %n, 0
1004  br i1 %tmp5, label %exit, label %loop.preheader
1005
1006loop.preheader:
1007  br label %loop
1008
1009loop:
1010  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1011  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1012  %within.bounds.1 = icmp ult i32 %i, %length.1
1013  %within.bounds.2 = icmp ult i32 %i, %length.2
1014  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
1015  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1016
1017  %i.i64 = zext i32 %i to i64
1018  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1019  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1020  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1021
1022  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1023  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1024  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
1025
1026  %i.next = add nuw i32 %i, 1
1027  %continue = icmp ult i32 %i.next, %n
1028  br i1 %continue, label %loop, label %exit
1029
1030exit:
1031  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1032  ret i32 %result
1033}
1034
1035define i32 @three_range_checks(i32* %array.1, i32 %length.1,
1036; CHECK-LABEL: @three_range_checks(
1037; CHECK-NEXT:  entry:
1038; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1039; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1040; CHECK:       loop.preheader:
1041; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1042; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1043; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1044; CHECK-NEXT:    [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1045; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1046; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
1047; CHECK-NEXT:    [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1048; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1049; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
1050; CHECK-NEXT:    [[TMP9:%.*]] = and i1 [[TMP2]], [[TMP5]]
1051; CHECK-NEXT:    [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1052; CHECK-NEXT:    br label [[LOOP:%.*]]
1053; CHECK:       loop:
1054; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1055; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1056; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP10]], i32 9) [ "deopt"() ]
1057; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1058; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
1059; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
1060; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1061; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
1062; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
1063; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1064; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
1065; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
1066; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1067; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1068; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1069; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1070; CHECK:       exit.loopexit:
1071; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1072; CHECK-NEXT:    br label [[EXIT]]
1073; CHECK:       exit:
1074; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1075; CHECK-NEXT:    ret i32 [[RESULT]]
1076;
1077  i32* %array.2, i32 %length.2,
1078  i32* %array.3, i32 %length.3, i32 %n) {
1079entry:
1080  %tmp5 = icmp eq i32 %n, 0
1081  br i1 %tmp5, label %exit, label %loop.preheader
1082
1083loop.preheader:
1084  br label %loop
1085
1086loop:
1087  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1088  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1089  %within.bounds.1 = icmp ult i32 %i, %length.1
1090  %within.bounds.2 = icmp ult i32 %i, %length.2
1091  %within.bounds.3 = icmp ult i32 %i, %length.3
1092  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
1093  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
1094  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1095
1096  %i.i64 = zext i32 %i to i64
1097  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1098  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1099  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1100
1101  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1102  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1103  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1104
1105  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
1106  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
1107  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1108
1109  %i.next = add nuw i32 %i, 1
1110  %continue = icmp ult i32 %i.next, %n
1111  br i1 %continue, label %loop, label %exit
1112
1113exit:
1114  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1115  ret i32 %result
1116}
1117
1118define i32 @three_guards(i32* %array.1, i32 %length.1,
1119; CHECK-LABEL: @three_guards(
1120; CHECK-NEXT:  entry:
1121; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1122; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1123; CHECK:       loop.preheader:
1124; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1125; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1126; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1127; CHECK-NEXT:    [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1128; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1129; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
1130; CHECK-NEXT:    [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1131; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1132; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
1133; CHECK-NEXT:    br label [[LOOP:%.*]]
1134; CHECK:       loop:
1135; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1136; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1137; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1138; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1139; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
1140; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
1141; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1142; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ]
1143; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
1144; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
1145; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1146; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ]
1147; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
1148; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
1149; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1150; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1151; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1152; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1153; CHECK:       exit.loopexit:
1154; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1155; CHECK-NEXT:    br label [[EXIT]]
1156; CHECK:       exit:
1157; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1158; CHECK-NEXT:    ret i32 [[RESULT]]
1159;
1160  i32* %array.2, i32 %length.2,
1161  i32* %array.3, i32 %length.3, i32 %n) {
1162entry:
1163  %tmp5 = icmp eq i32 %n, 0
1164  br i1 %tmp5, label %exit, label %loop.preheader
1165
1166loop.preheader:
1167  br label %loop
1168
1169loop:
1170
1171  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1172  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1173
1174  %within.bounds.1 = icmp ult i32 %i, %length.1
1175  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
1176
1177  %i.i64 = zext i32 %i to i64
1178  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1179  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1180  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1181
1182  %within.bounds.2 = icmp ult i32 %i, %length.2
1183  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
1184
1185  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1186  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1187  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1188
1189  %within.bounds.3 = icmp ult i32 %i, %length.3
1190  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
1191
1192  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
1193  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
1194  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1195
1196  %i.next = add nuw i32 %i, 1
1197  %continue = icmp ult i32 %i.next, %n
1198  br i1 %continue, label %loop, label %exit
1199
1200exit:
1201  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1202  ret i32 %result
1203}
1204
1205define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
1206; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition(
1207; CHECK-NEXT:  entry:
1208; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1209; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1210; CHECK:       loop.preheader:
1211; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
1212; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1213; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1214; CHECK-NEXT:    br label [[LOOP:%.*]]
1215; CHECK:       loop:
1216; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1217; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1218; CHECK-NEXT:    [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
1219; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]]
1220; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1221; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1222; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1223; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1224; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1225; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1226; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1227; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1228; CHECK:       exit.loopexit:
1229; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1230; CHECK-NEXT:    br label [[EXIT]]
1231; CHECK:       exit:
1232; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1233; CHECK-NEXT:    ret i32 [[RESULT]]
1234;
1235entry:
1236  %tmp5 = icmp eq i32 %n, 0
1237  br i1 %tmp5, label %exit, label %loop.preheader
1238
1239loop.preheader:
1240  br label %loop
1241
1242loop:
1243  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1244  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1245  %within.bounds = icmp ult i32 %i, %length
1246  %unrelated.cond = icmp ult i32 %x, %length
1247  %guard.cond = and i1 %within.bounds, %unrelated.cond
1248  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1249
1250  %i.i64 = zext i32 %i to i64
1251  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1252  %array.i = load i32, i32* %array.i.ptr, align 4
1253  %loop.acc.next = add i32 %loop.acc, %array.i
1254
1255  %i.next = add nuw i32 %i, 1
1256  %continue = icmp ult i32 %i.next, %n
1257  br i1 %continue, label %loop, label %exit
1258
1259exit:
1260  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1261  ret i32 %result
1262}
1263
1264; Don't change the guard condition if there were no widened subconditions
1265define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
1266; CHECK-LABEL: @test_no_widened_conditions(
1267; CHECK-NEXT:  entry:
1268; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1269; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1270; CHECK:       loop.preheader:
1271; CHECK-NEXT:    br label [[LOOP:%.*]]
1272; CHECK:       loop:
1273; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1274; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1275; CHECK-NEXT:    [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]]
1276; CHECK-NEXT:    [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]]
1277; CHECK-NEXT:    [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]]
1278; CHECK-NEXT:    [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]]
1279; CHECK-NEXT:    [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]]
1280; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1281; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1282; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1283; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1284; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1285; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1286; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1287; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1288; CHECK:       exit.loopexit:
1289; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1290; CHECK-NEXT:    br label [[EXIT]]
1291; CHECK:       exit:
1292; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1293; CHECK-NEXT:    ret i32 [[RESULT]]
1294;
1295entry:
1296  %tmp5 = icmp eq i32 %n, 0
1297  br i1 %tmp5, label %exit, label %loop.preheader
1298
1299loop.preheader:
1300  br label %loop
1301
1302loop:
1303  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1304  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1305  %unrelated.cond.1 = icmp eq i32 %x1, %i
1306  %unrelated.cond.2 = icmp eq i32 %x2, %i
1307  %unrelated.cond.3 = icmp eq i32 %x3, %i
1308  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
1309  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
1310
1311  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1312
1313  %i.i64 = zext i32 %i to i64
1314  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1315  %array.i = load i32, i32* %array.i.ptr, align 4
1316  %loop.acc.next = add i32 %loop.acc, %array.i
1317
1318  %i.next = add nuw i32 %i, 1
1319  %continue = icmp ult i32 %i.next, %n
1320  br i1 %continue, label %loop, label %exit
1321
1322exit:
1323  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1324  ret i32 %result
1325}
1326
1327define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
1328; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound(
1329; CHECK-NEXT:  entry:
1330; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1331; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1332; CHECK:       loop.preheader:
1333; CHECK-NEXT:    br label [[LOOP:%.*]]
1334; CHECK:       loop:
1335; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1336; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1337; CHECK-NEXT:    [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]]
1338; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]]
1339; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1340; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1341; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1342; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1343; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1344; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
1345; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1346; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1347; CHECK:       exit.loopexit:
1348; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1349; CHECK-NEXT:    br label [[EXIT]]
1350; CHECK:       exit:
1351; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1352; CHECK-NEXT:    ret i32 [[RESULT]]
1353;
1354entry:
1355  %tmp5 = icmp sle i32 %n, 0
1356  br i1 %tmp5, label %exit, label %loop.preheader
1357
1358loop.preheader:
1359  br label %loop
1360
1361loop:
1362  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1363  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1364  %bound = add i32 %i, %x
1365  %within.bounds = icmp ult i32 %i, %bound
1366  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1367
1368  %i.i64 = zext i32 %i to i64
1369  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1370  %array.i = load i32, i32* %array.i.ptr, align 4
1371  %loop.acc.next = add i32 %loop.acc, %array.i
1372
1373  %i.next = add nsw i32 %i, 1
1374  %continue = icmp slt i32 %i.next, %n
1375  br i1 %continue, label %loop, label %exit
1376
1377exit:
1378  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1379  ret i32 %result
1380}
1381
1382define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
1383; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate(
1384; CHECK-NEXT:  entry:
1385; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1386; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1387; CHECK:       loop.preheader:
1388; CHECK-NEXT:    br label [[LOOP:%.*]]
1389; CHECK:       loop:
1390; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1391; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1392; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]]
1393; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1394; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1395; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1396; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1397; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1398; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
1399; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1400; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1401; CHECK:       exit.loopexit:
1402; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1403; CHECK-NEXT:    br label [[EXIT]]
1404; CHECK:       exit:
1405; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1406; CHECK-NEXT:    ret i32 [[RESULT]]
1407;
1408entry:
1409  %tmp5 = icmp sle i32 %n, 0
1410  br i1 %tmp5, label %exit, label %loop.preheader
1411
1412loop.preheader:
1413  br label %loop
1414
1415loop:
1416  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1417  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1418  %guard.cond = icmp eq i32 %i, %x
1419  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1420
1421  %i.i64 = zext i32 %i to i64
1422  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1423  %array.i = load i32, i32* %array.i.ptr, align 4
1424  %loop.acc.next = add i32 %loop.acc, %array.i
1425
1426  %i.next = add nsw i32 %i, 1
1427  %continue = icmp slt i32 %i.next, %n
1428  br i1 %continue, label %loop, label %exit
1429
1430exit:
1431  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1432  ret i32 %result
1433}
1434
1435define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
1436; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length(
1437; CHECK-NEXT:  entry:
1438; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1439; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1440; CHECK:       loop.preheader:
1441; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32
1442; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1443; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]]
1444; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1445; CHECK-NEXT:    br label [[LOOP:%.*]]
1446; CHECK:       loop:
1447; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1448; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1449; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1450; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1451; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1452; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1453; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1454; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1455; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1456; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1457; CHECK:       exit.loopexit:
1458; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1459; CHECK-NEXT:    br label [[EXIT]]
1460; CHECK:       exit:
1461; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1462; CHECK-NEXT:    ret i32 [[RESULT]]
1463;
1464entry:
1465  %tmp5 = icmp eq i32 %n, 0
1466  br i1 %tmp5, label %exit, label %loop.preheader
1467
1468loop.preheader:
1469  br label %loop
1470
1471loop:
1472  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1473  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1474  %length = zext i16 %length.i16 to i32
1475  %within.bounds = icmp ult i32 %i, %length
1476  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1477
1478  %i.i64 = zext i32 %i to i64
1479  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1480  %array.i = load i32, i32* %array.i.ptr, align 4
1481  %loop.acc.next = add i32 %loop.acc, %array.i
1482
1483  %i.next = add nuw i32 %i, 1
1484  %continue = icmp ult i32 %i.next, %n
1485  br i1 %continue, label %loop, label %exit
1486
1487exit:
1488  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1489  ret i32 %result
1490}
1491
1492define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
1493; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length(
1494; CHECK-NEXT:  entry:
1495; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1496; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1497; CHECK:       loop.preheader:
1498; CHECK-NEXT:    br label [[LOOP:%.*]]
1499; CHECK:       loop:
1500; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1501; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1502; CHECK-NEXT:    [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]]
1503; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]]
1504; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]]
1505; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1506; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1507; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1508; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1509; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1510; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1511; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1512; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1513; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1514; CHECK:       exit.loopexit:
1515; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1516; CHECK-NEXT:    br label [[EXIT]]
1517; CHECK:       exit:
1518; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1519; CHECK-NEXT:    ret i32 [[RESULT]]
1520;
1521entry:
1522  %tmp5 = icmp eq i32 %n, 0
1523  br i1 %tmp5, label %exit, label %loop.preheader
1524
1525loop.preheader:
1526  br label %loop
1527
1528loop:
1529  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1530  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1531  %length.udiv = udiv i32 %length, %divider
1532  %within.bounds = icmp ult i32 %i, %length.udiv
1533  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1534
1535  %i.i64 = zext i32 %i to i64
1536  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1537  %array.i = load i32, i32* %array.i.ptr, align 4
1538  %loop.acc.next = add i32 %loop.acc, %array.i
1539
1540  %i.next = add nuw i32 %i, 1
1541  %continue = icmp ult i32 %i.next, %n
1542  br i1 %continue, label %loop, label %exit
1543
1544exit:
1545  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1546  ret i32 %result
1547}
1548
1549
1550; This is a case where the length information tells us that the guard
1551; must trigger on some iteration.
1552define i32 @provably_taken(i32* %array, i32* %length.ptr) {
1553; CHECK-LABEL: @provably_taken(
1554; CHECK-NEXT:  loop.preheader:
1555; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], align 4, !range [[RNG1:![0-9]+]]
1556; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]]
1557; CHECK-NEXT:    br label [[LOOP:%.*]]
1558; CHECK:       loop:
1559; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1560; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1561; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false, i32 9) [ "deopt"() ]
1562; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1563; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1564; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1565; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1566; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1567; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200
1568; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1569; CHECK:       exit:
1570; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1571; CHECK-NEXT:    ret i32 [[RESULT]]
1572;
1573loop.preheader:
1574  %length = load i32, i32* %length.ptr, !range !{i32 0, i32 50}
1575  br label %loop
1576
1577loop:
1578  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1579  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1580  %within.bounds = icmp ult i32 %i, %length
1581  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1582
1583  %i.i64 = zext i32 %i to i64
1584  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1585  %array.i = load i32, i32* %array.i.ptr, align 4
1586  %loop.acc.next = add i32 %loop.acc, %array.i
1587
1588  %i.next = add nuw i32 %i, 1
1589  %continue = icmp slt i32 %i.next, 200
1590  br i1 %continue, label %loop, label %exit
1591
1592exit:
1593  %result = phi i32 [ %loop.acc.next, %loop ]
1594  ret i32 %result
1595}
1596
1597; NE Check (as produced by LFTR) where we can prove Start < End via simple
1598; instruction analysis
1599define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) {
1600; CHECK-LABEL: @ne_latch_zext(
1601; CHECK-NEXT:  loop.preheader:
1602; CHECK-NEXT:    [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1603; CHECK-NEXT:    [[NPLUS1:%.*]] = add nuw nsw i32 [[N]], 1
1604; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[NPLUS1]], [[LENGTH:%.*]]
1605; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1606; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1607; CHECK-NEXT:    br label [[LOOP:%.*]]
1608; CHECK:       loop:
1609; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1610; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1611; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1612; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1613; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1614; CHECK:       exit:
1615; CHECK-NEXT:    ret i32 0
1616;
1617loop.preheader:
1618  %n = zext i16 %n16 to i32
1619  %nplus1 = add nsw nuw i32 %n, 1
1620  br label %loop
1621
1622loop:
1623  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1624  %within.bounds = icmp ult i32 %i, %length
1625  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1626
1627  %i.next = add nsw nuw i32 %i, 1
1628  %continue = icmp ne i32 %i.next, %nplus1
1629  br i1 %continue, label %loop, label %exit
1630
1631exit:
1632  ret i32 0
1633}
1634
1635; Same as previous, but with a pre-increment test since this is easier to match
1636define i32 @ne_latch_zext_preinc(i32* %array, i32 %length, i16 %n16) {
1637; CHECK-LABEL: @ne_latch_zext_preinc(
1638; CHECK-NEXT:  loop.preheader:
1639; CHECK-NEXT:    [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1640; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1641; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1642; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1643; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1644; CHECK-NEXT:    br label [[LOOP:%.*]]
1645; CHECK:       loop:
1646; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1647; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1648; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1649; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1650; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1651; CHECK:       exit:
1652; CHECK-NEXT:    ret i32 0
1653;
1654loop.preheader:
1655  %n = zext i16 %n16 to i32
1656  br label %loop
1657
1658loop:
1659  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1660  %within.bounds = icmp ult i32 %i, %length
1661  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1662
1663  %i.next = add nuw i32 %i, 1
1664  %continue = icmp ne i32 %i, %n
1665  br i1 %continue, label %loop, label %exit
1666
1667exit:
1668  ret i32 0
1669}
1670
1671; NE Check (as produced by LFTR) where we can prove Start < End via the
1672; condition guarding the loop entry.
1673define i32 @ne_latch_dom_check(i32* %array, i32 %length, i32 %n) {
1674; CHECK-LABEL: @ne_latch_dom_check(
1675; CHECK-NEXT:  entry:
1676; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1677; CHECK-NEXT:    [[NPLUS1:%.*]] = add nuw i32 [[N]], 1
1678; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1679; CHECK:       loop.preheader:
1680; CHECK-NEXT:    br label [[LOOP:%.*]]
1681; CHECK:       loop:
1682; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1683; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1684; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1685; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1686; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1687; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1688; CHECK:       exit.loopexit:
1689; CHECK-NEXT:    br label [[EXIT]]
1690; CHECK:       exit:
1691; CHECK-NEXT:    ret i32 0
1692;
1693entry:
1694  %tmp5 = icmp sle i32 %n, 0
1695  %nplus1 = add nuw i32 %n, 1
1696  br i1 %tmp5, label %exit, label %loop.preheader
1697
1698loop.preheader:
1699  br label %loop
1700
1701loop:
1702  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1703  %within.bounds = icmp ult i32 %i, %length
1704  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1705
1706  %i.next = add nsw nuw i32 %i, 1
1707  %continue = icmp ne i32 %i.next, %nplus1
1708  br i1 %continue, label %loop, label %exit
1709
1710exit:
1711  ret i32 0
1712}
1713
1714; Same as previous, but easier to match
1715define i32 @ne_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) {
1716; CHECK-LABEL: @ne_latch_dom_check_preinc(
1717; CHECK-NEXT:  entry:
1718; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1719; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1720; CHECK:       loop.preheader:
1721; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1722; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1723; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1724; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1725; CHECK-NEXT:    br label [[LOOP:%.*]]
1726; CHECK:       loop:
1727; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1728; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1729; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1730; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1731; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1732; CHECK:       exit.loopexit:
1733; CHECK-NEXT:    br label [[EXIT]]
1734; CHECK:       exit:
1735; CHECK-NEXT:    ret i32 0
1736;
1737entry:
1738  %tmp5 = icmp sle i32 %n, 0
1739  br i1 %tmp5, label %exit, label %loop.preheader
1740
1741loop.preheader:
1742  br label %loop
1743
1744loop:
1745  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1746  %within.bounds = icmp ult i32 %i, %length
1747  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1748
1749  %i.next = add nuw i32 %i, 1
1750  %continue = icmp ne i32 %i, %n
1751  br i1 %continue, label %loop, label %exit
1752
1753exit:
1754  ret i32 0
1755}
1756
1757; Same as previous, except swapped br/cmp
1758define i32 @eq_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) {
1759; CHECK-LABEL: @eq_latch_dom_check_preinc(
1760; CHECK-NEXT:  entry:
1761; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1762; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1763; CHECK:       loop.preheader:
1764; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1765; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1766; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1767; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1768; CHECK-NEXT:    br label [[LOOP:%.*]]
1769; CHECK:       loop:
1770; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1771; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1772; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1773; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i32 [[I]], [[N]]
1774; CHECK-NEXT:    br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
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  br i1 %tmp5, label %exit, label %loop.preheader
1783
1784loop.preheader:
1785  br label %loop
1786
1787loop:
1788  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1789  %within.bounds = icmp ult i32 %i, %length
1790  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1791
1792  %i.next = add nuw i32 %i, 1
1793  %done = icmp eq i32 %i, %n
1794  br i1 %done, label %exit, label %loop
1795
1796exit:
1797  ret i32 0
1798}
1799
1800
1801; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap
1802; around several times or even be infinite)
1803define i32 @neg_ne_latch_mod_step(i32* %array, i32 %length, i16 %n16) {
1804; CHECK-LABEL: @neg_ne_latch_mod_step(
1805; CHECK-NEXT:  loop.preheader:
1806; CHECK-NEXT:    [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1807; CHECK-NEXT:    br label [[LOOP:%.*]]
1808; CHECK:       loop:
1809; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1810; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1811; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1812; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 3
1813; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1814; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1815; CHECK:       exit:
1816; CHECK-NEXT:    ret i32 0
1817;
1818loop.preheader:
1819  %n = zext i16 %n16 to i32
1820  br label %loop
1821
1822loop:
1823  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1824  %within.bounds = icmp ult i32 %i, %length
1825  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1826
1827  %i.next = add i32 %i, 3
1828  %continue = icmp ne i32 %i, %n
1829  br i1 %continue, label %loop, label %exit
1830
1831exit:
1832  ret i32 0
1833}
1834
1835; NE latch - TODO: could prove (end-start) mod step == 0
1836define i32 @ne_latch_mod_step(i32* %array, i32 %length) {
1837; CHECK-LABEL: @ne_latch_mod_step(
1838; CHECK-NEXT:  loop.preheader:
1839; CHECK-NEXT:    br label [[LOOP:%.*]]
1840; CHECK:       loop:
1841; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1842; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1843; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1844; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 2
1845; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I]], 400
1846; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1847; CHECK:       exit:
1848; CHECK-NEXT:    ret i32 0
1849;
1850loop.preheader:
1851  br label %loop
1852
1853loop:
1854  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1855  %within.bounds = icmp ult i32 %i, %length
1856  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1857
1858  %i.next = add nuw i32 %i, 2
1859  %continue = icmp ne i32 %i, 400
1860  br i1 %continue, label %loop, label %exit
1861
1862exit:
1863  ret i32 0
1864}
1865
1866; NE Latch - but end > start so wraps around and not equivelent to a ult
1867define i32 @neg_ne_latch_swapped_order(i32* %array, i32 %length) {
1868; CHECK-LABEL: @neg_ne_latch_swapped_order(
1869; CHECK-NEXT:  loop.preheader:
1870; CHECK-NEXT:    br label [[LOOP:%.*]]
1871; CHECK:       loop:
1872; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1873; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1874; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1875; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
1876; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I]], 0
1877; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1878; CHECK:       exit:
1879; CHECK-NEXT:    ret i32 0
1880;
1881loop.preheader:
1882  br label %loop
1883
1884loop:
1885  %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
1886  %within.bounds = icmp ult i32 %i, %length
1887  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1888
1889  %i.next = add i32 %i, 1
1890  %continue = icmp ne i32 %i, 0
1891  br i1 %continue, label %loop, label %exit
1892
1893exit:
1894  ret i32 0
1895}
1896
1897; Negative test, make sure we don't crash on unconditional latches
1898; TODO: there's no reason we shouldn't be able to predicate the
1899; condition for an statically infinite loop.
1900define i32 @unconditional_latch(i32* %a, i32 %length) {
1901; CHECK-LABEL: @unconditional_latch(
1902; CHECK-NEXT:  loop.preheader:
1903; CHECK-NEXT:    br label [[LOOP:%.*]]
1904; CHECK:       loop:
1905; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1906; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1907; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1908; CHECK-NEXT:    store volatile i32 0, i32* [[A:%.*]], align 4
1909; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
1910; CHECK-NEXT:    br label [[LOOP]]
1911;
1912loop.preheader:
1913  br label %loop
1914
1915loop:
1916  %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
1917  %within.bounds = icmp ult i32 %i, %length
1918  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1919  store volatile i32 0, i32* %a
1920  %i.next = add i32 %i, 1
1921  br label %loop
1922}
1923