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