1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
3; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
4
5declare void @llvm.experimental.guard(i1, ...)
6
7define i32 @signed_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
8; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit(
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:%.*]] = add i32 [[N]], -1
14; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
15; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i32 [[LOWERLIMIT:%.*]], 1
16; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
17; CHECK-NEXT:    br label [[LOOP:%.*]]
18; CHECK:       loop:
19; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
20; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
21; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
22; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
23; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
24; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
25; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
26; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
27; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
28; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sgt i32 [[I]], [[LOWERLIMIT]]
29; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
30; CHECK:       exit.loopexit:
31; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
32; CHECK-NEXT:    br label [[EXIT]]
33; CHECK:       exit:
34; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
35; CHECK-NEXT:    ret i32 [[RESULT]]
36;
37entry:
38  %tmp5 = icmp eq i32 %n, 0
39  br i1 %tmp5, label %exit, label %loop.preheader
40
41loop.preheader:
42  br label %loop
43
44loop:
45  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
46  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
47  %i.next = add nsw i32 %i, -1
48  %within.bounds = icmp ult i32 %i.next, %length
49  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
50  %i.i64 = zext i32 %i.next to i64
51  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
52  %array.i = load i32, i32* %array.i.ptr, align 4
53  %loop.acc.next = add i32 %loop.acc, %array.i
54  %continue = icmp sgt i32 %i, %lowerlimit
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_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
63; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit(
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:%.*]] = add i32 [[N]], -1
69; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
70; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[LOWERLIMIT:%.*]], 1
71; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
72; CHECK-NEXT:    br label [[LOOP:%.*]]
73; CHECK:       loop:
74; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
75; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
76; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
77; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
78; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
79; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
80; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
81; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
82; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
83; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], [[LOWERLIMIT]]
84; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
85; CHECK:       exit.loopexit:
86; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
87; CHECK-NEXT:    br label [[EXIT]]
88; CHECK:       exit:
89; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
90; CHECK-NEXT:    ret i32 [[RESULT]]
91;
92entry:
93  %tmp5 = icmp eq i32 %n, 0
94  br i1 %tmp5, label %exit, label %loop.preheader
95
96loop.preheader:
97  br label %loop
98
99loop:
100  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
101  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
102  %i.next = add nsw i32 %i, -1
103  %within.bounds = icmp ult i32 %i.next, %length
104  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
105  %i.i64 = zext i32 %i.next to i64
106  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
107  %array.i = load i32, i32* %array.i.ptr, align 4
108  %loop.acc.next = add i32 %loop.acc, %array.i
109  %continue = icmp ugt i32 %i, %lowerlimit
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
117
118; if we predicated the loop, the guard will definitely fail and we will
119; deoptimize early on.
120define i32 @unsigned_reverse_loop_n_to_0(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
121; CHECK-LABEL: @unsigned_reverse_loop_n_to_0(
122; CHECK-NEXT:  entry:
123; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
124; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
125; CHECK:       loop.preheader:
126; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
127; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
128; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], false
129; CHECK-NEXT:    br label [[LOOP:%.*]]
130; CHECK:       loop:
131; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
132; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
133; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
134; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
135; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
136; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
137; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
138; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
139; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
140; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0
141; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
142; CHECK:       exit.loopexit:
143; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
144; CHECK-NEXT:    br label [[EXIT]]
145; CHECK:       exit:
146; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
147; CHECK-NEXT:    ret i32 [[RESULT]]
148;
149entry:
150  %tmp5 = icmp eq i32 %n, 0
151  br i1 %tmp5, label %exit, label %loop.preheader
152
153loop.preheader:
154  br label %loop
155
156loop:
157  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
158  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
159  %i.next = add nsw i32 %i, -1
160  %within.bounds = icmp ult i32 %i.next, %length
161  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
162  %i.i64 = zext i32 %i.next to i64
163  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
164  %array.i = load i32, i32* %array.i.ptr, align 4
165  %loop.acc.next = add i32 %loop.acc, %array.i
166  %continue = icmp ugt i32 %i, 0
167  br i1 %continue, label %loop, label %exit
168
169exit:
170  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
171  ret i32 %result
172}
173
174; do not loop predicate when the range has step -1 and latch has step 1.
175define i32 @reverse_loop_range_step_increment(i32 %n, i32* %array, i32 %length) {
176; CHECK-LABEL: @reverse_loop_range_step_increment(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
179; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
180; CHECK:       loop.preheader:
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]] ], [ [[N]], [[LOOP_PREHEADER]] ]
185; CHECK-NEXT:    [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ]
186; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[IRC]], 1
187; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]]
188; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
189; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[IRC]] to i64
190; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
191; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
192; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
193; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
194; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534
195; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
196; CHECK:       exit.loopexit:
197; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
198; CHECK-NEXT:    br label [[EXIT]]
199; CHECK:       exit:
200; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
201; CHECK-NEXT:    ret i32 [[RESULT]]
202;
203entry:
204  %tmp5 = icmp eq i32 %n, 0
205  br i1 %tmp5, label %exit, label %loop.preheader
206
207loop.preheader:
208  br label %loop
209
210loop:
211  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
212  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
213  %irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ]
214  %i.inc = add nuw nsw i32 %irc, 1
215  %within.bounds = icmp ult i32 %irc, %length
216  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
217  %i.i64 = zext i32 %irc to i64
218  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
219  %array.i = load i32, i32* %array.i.ptr, align 4
220  %i.next = add nsw i32 %i, -1
221  %loop.acc.next = add i32 %loop.acc, %array.i
222  %continue = icmp ugt i32 %i, 65534
223  br i1 %continue, label %loop, label %exit
224
225exit:
226  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
227  ret i32 %result
228}
229
230define i32 @signed_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
231; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal(
232; CHECK-NEXT:  entry:
233; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
234; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
235; CHECK:       loop.preheader:
236; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
237; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
238; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1
239; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
240; CHECK-NEXT:    br label [[LOOP:%.*]]
241; CHECK:       loop:
242; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
243; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
244; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
245; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
246; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
247; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
248; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
249; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
250; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
251; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]]
252; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
253; CHECK:       exit.loopexit:
254; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
255; CHECK-NEXT:    br label [[EXIT]]
256; CHECK:       exit:
257; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
258; CHECK-NEXT:    ret i32 [[RESULT]]
259;
260entry:
261  %tmp5 = icmp eq i32 %n, 0
262  br i1 %tmp5, label %exit, label %loop.preheader
263
264loop.preheader:
265  br label %loop
266
267loop:
268  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
269  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
270  %i.next = add nsw i32 %i, -1
271  %within.bounds = icmp ult i32 %i.next, %length
272  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
273  %i.i64 = zext i32 %i.next to i64
274  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
275  %array.i = load i32, i32* %array.i.ptr, align 4
276  %loop.acc.next = add i32 %loop.acc, %array.i
277  %continue = icmp sge i32 %i, %lowerlimit
278  br i1 %continue, label %loop, label %exit
279
280exit:
281  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
282  ret i32 %result
283}
284
285define i32 @unsigned_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
286; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal(
287; CHECK-NEXT:  entry:
288; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
289; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
290; CHECK:       loop.preheader:
291; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
292; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
293; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1
294; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
295; CHECK-NEXT:    br label [[LOOP:%.*]]
296; CHECK:       loop:
297; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
298; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
299; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
300; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
301; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
302; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
303; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
304; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
305; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
306; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]]
307; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
308; CHECK:       exit.loopexit:
309; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
310; CHECK-NEXT:    br label [[EXIT]]
311; CHECK:       exit:
312; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
313; CHECK-NEXT:    ret i32 [[RESULT]]
314;
315entry:
316  %tmp5 = icmp eq i32 %n, 0
317  br i1 %tmp5, label %exit, label %loop.preheader
318
319loop.preheader:
320  br label %loop
321
322loop:
323  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
324  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
325  %i.next = add nsw i32 %i, -1
326  %within.bounds = icmp ult i32 %i.next, %length
327  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
328  %i.i64 = zext i32 %i.next to i64
329  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
330  %array.i = load i32, i32* %array.i.ptr, align 4
331  %loop.acc.next = add i32 %loop.acc, %array.i
332  %continue = icmp uge i32 %i, %lowerlimit
333  br i1 %continue, label %loop, label %exit
334
335exit:
336  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
337  ret i32 %result
338}
339
340
341; if we predicated the loop, the guard will definitely fail and we will
342; deoptimize early on.
343define i32 @unsigned_reverse_loop_n_to_1(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
344; CHECK-LABEL: @unsigned_reverse_loop_n_to_1(
345; CHECK-NEXT:  entry:
346; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
347; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
348; CHECK:       loop.preheader:
349; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
350; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
351; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], false
352; CHECK-NEXT:    br label [[LOOP:%.*]]
353; CHECK:       loop:
354; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
355; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
356; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
357; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
358; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
359; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
360; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
361; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
362; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
363; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1
364; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
365; CHECK:       exit.loopexit:
366; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
367; CHECK-NEXT:    br label [[EXIT]]
368; CHECK:       exit:
369; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
370; CHECK-NEXT:    ret i32 [[RESULT]]
371;
372entry:
373  %tmp5 = icmp eq i32 %n, 0
374  br i1 %tmp5, label %exit, label %loop.preheader
375
376loop.preheader:
377  br label %loop
378
379loop:
380  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
381  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
382  %i.next = add nsw i32 %i, -1
383  %within.bounds = icmp ult i32 %i.next, %length
384  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
385  %i.i64 = zext i32 %i.next to i64
386  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
387  %array.i = load i32, i32* %array.i.ptr, align 4
388  %loop.acc.next = add i32 %loop.acc, %array.i
389  %continue = icmp uge i32 %i, 1
390  br i1 %continue, label %loop, label %exit
391
392exit:
393  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
394  ret i32 %result
395}
396
397