1; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
2; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
3
4declare void @llvm.experimental.guard(i1, ...)
5
6define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
7; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check
8entry:
9  %tmp5 = icmp eq i32 %n, 0
10  br i1 %tmp5, label %exit, label %loop.preheader
11
12loop.preheader:
13; CHECK: loop.preheader:
14; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
15; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp ult i32 [[max_index]], %length
16; CHECK-NEXT: br label %loop
17  br label %loop
18
19loop:
20; CHECK: loop:
21; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
22  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
23  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
24  %within.bounds = icmp ult i32 %i, %length
25  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
26
27  %i.i64 = zext i32 %i to i64
28  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
29  %array.i = load i32, i32* %array.i.ptr, align 4
30  %loop.acc.next = add i32 %loop.acc, %array.i
31
32  %i.next = add nuw i32 %i, 1
33  %continue = icmp ult i32 %i.next, %n
34  br i1 %continue, label %loop, label %exit
35
36exit:
37  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
38  ret i32 %result
39}
40
41define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) {
42; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check
43entry:
44  %tmp5 = icmp eq i32 %n, 0
45  br i1 %tmp5, label %exit, label %loop.preheader
46
47loop.preheader:
48; CHECK: loop.preheader:
49; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
50; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp ult i32 [[max_index]], %length
51; CHECK-NEXT: br label %loop
52  br label %loop
53
54loop:
55; CHECK: loop:
56; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
57  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
58  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
59  %within.bounds = icmp ugt i32 %length, %i
60  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
61
62  %i.i64 = zext i32 %i to i64
63  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
64  %array.i = load i32, i32* %array.i.ptr, align 4
65  %loop.acc.next = add i32 %loop.acc, %array.i
66
67  %i.next = add nuw i32 %i, 1
68  %continue = icmp ult i32 %i.next, %n
69  br i1 %continue, label %loop, label %exit
70
71exit:
72  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
73  ret i32 %result
74}
75
76
77define i32 @two_range_checks(i32* %array.1, i32 %length.1,
78                             i32* %array.2, i32 %length.2, i32 %n) {
79; CHECK-LABEL: @two_range_checks
80entry:
81  %tmp5 = icmp eq i32 %n, 0
82  br i1 %tmp5, label %exit, label %loop.preheader
83
84loop.preheader:
85; CHECK: loop.preheader:
86; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
87; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = icmp ult i32 [[max_index]], %length.{{1|2}}
88; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = icmp ult i32 [[max_index]], %length.{{1|2}}
89; CHECK-NEXT: br label %loop
90  br label %loop
91
92loop:
93; CHECK: loop:
94; CHECK: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
95; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
96  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
97  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
98  %within.bounds.1 = icmp ult i32 %i, %length.1
99  %within.bounds.2 = icmp ult i32 %i, %length.2
100  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
101  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
102
103  %i.i64 = zext i32 %i to i64
104  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
105  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
106  %loop.acc.1 = add i32 %loop.acc, %array.1.i
107
108  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
109  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
110  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
111
112  %i.next = add nuw i32 %i, 1
113  %continue = icmp ult i32 %i.next, %n
114  br i1 %continue, label %loop, label %exit
115
116exit:
117  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
118  ret i32 %result
119}
120
121define i32 @three_range_checks(i32* %array.1, i32 %length.1,
122                               i32* %array.2, i32 %length.2,
123                               i32* %array.3, i32 %length.3, i32 %n) {
124; CHECK-LABEL: @three_range_checks
125entry:
126  %tmp5 = icmp eq i32 %n, 0
127  br i1 %tmp5, label %exit, label %loop.preheader
128
129loop.preheader:
130; CHECK: loop.preheader:
131; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
132; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = icmp ult i32 [[max_index]], %length.{{1|2|3}}
133; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = icmp ult i32 [[max_index]], %length.{{1|2|3}}
134; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = icmp ult i32 [[max_index]], %length.{{1|2|3}}
135; CHECK-NEXT: br label %loop
136  br label %loop
137
138loop:
139; CHECK: loop:
140; CHECK: [[wide_cond_and:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
141; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_and]], [[wide_cond_3]]
142; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
143  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
144  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
145  %within.bounds.1 = icmp ult i32 %i, %length.1
146  %within.bounds.2 = icmp ult i32 %i, %length.2
147  %within.bounds.3 = icmp ult i32 %i, %length.3
148  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
149  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
150  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
151
152  %i.i64 = zext i32 %i to i64
153  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
154  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
155  %loop.acc.1 = add i32 %loop.acc, %array.1.i
156
157  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
158  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
159  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
160
161  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
162  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
163  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
164
165  %i.next = add nuw i32 %i, 1
166  %continue = icmp ult i32 %i.next, %n
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
174define i32 @three_guards(i32* %array.1, i32 %length.1,
175                         i32* %array.2, i32 %length.2,
176                         i32* %array.3, i32 %length.3, i32 %n) {
177; CHECK-LABEL: @three_guards
178entry:
179  %tmp5 = icmp eq i32 %n, 0
180  br i1 %tmp5, label %exit, label %loop.preheader
181
182loop.preheader:
183; CHECK: loop.preheader:
184; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
185; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = icmp ult i32 [[max_index]], %length.1
186; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = icmp ult i32 [[max_index]], %length.2
187; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = icmp ult i32 [[max_index]], %length.3
188; CHECK-NEXT: br label %loop
189  br label %loop
190
191loop:
192; CHECK: loop:
193; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_1]], i32 9) [ "deopt"() ]
194; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_2]], i32 9) [ "deopt"() ]
195; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_3]], i32 9) [ "deopt"() ]
196
197  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
198  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
199
200  %within.bounds.1 = icmp ult i32 %i, %length.1
201  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
202
203  %i.i64 = zext i32 %i to i64
204  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
205  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
206  %loop.acc.1 = add i32 %loop.acc, %array.1.i
207
208  %within.bounds.2 = icmp ult i32 %i, %length.2
209  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
210
211  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
212  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
213  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
214
215  %within.bounds.3 = icmp ult i32 %i, %length.3
216  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
217
218  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
219  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
220  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
221
222  %i.next = add nuw i32 %i, 1
223  %continue = icmp ult i32 %i.next, %n
224  br i1 %continue, label %loop, label %exit
225
226exit:
227  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
228  ret i32 %result
229}
230
231define i32 @signed_loop_start_to_n_sge_0_check(i32* %array, i32 %length, i32 %start, i32 %n) {
232; CHECK-LABEL: @signed_loop_start_to_n_sge_0_check
233entry:
234  %tmp5 = icmp eq i32 %n, 0
235  br i1 %tmp5, label %exit, label %loop.preheader
236
237loop.preheader:
238; CHECK: loop.preheader:
239; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp sge i32 %start, 0
240; CHECK-NEXT: br label %loop
241  br label %loop
242
243loop:
244; CHECK: loop:
245; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
246  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
247  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
248  %within.bounds = icmp sge i32 %i, 0
249  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
250
251  %i.i64 = zext i32 %i to i64
252  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
253  %array.i = load i32, i32* %array.i.ptr, align 4
254  %loop.acc.next = add i32 %loop.acc, %array.i
255
256  %i.next = add nsw i32 %i, 1
257  %continue = icmp slt i32 %i.next, %n
258  br i1 %continue, label %loop, label %exit
259
260exit:
261  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
262  ret i32 %result
263}
264
265define i32 @signed_loop_start_to_n_upper_slt_length_check(i32* %array, i32 %length, i32 %start, i32 %n) {
266; CHECK-LABEL: @signed_loop_start_to_n_upper_slt_length_check
267entry:
268  %tmp5 = icmp sle i32 %n, 0
269  br i1 %tmp5, label %exit, label %loop.preheader
270
271loop.preheader:
272; CHECK: loop.preheader:
273; CHECK: [[start_1:[^ ]+]] = add i32 %start, 1
274; CHECK-NEXT: [[n_sgt_start_1:[^ ]+]] = icmp sgt i32 %n, [[start_1]]
275; CHECK-NEXT: [[smax:[^ ]+]] = select i1 [[n_sgt_start_1]], i32 %n, i32 [[start_1]]
276; CHECK-NEXT: [[max_index:[^ ]+]] = add i32 [[smax]], -1
277; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp slt i32 [[max_index]], %length
278; CHECK-NEXT: br label %loop
279  br label %loop
280
281loop:
282; CHECK: loop:
283; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
284  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
285  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
286  %within.bounds = icmp slt i32 %i, %length
287  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
288
289  %i.i64 = zext i32 %i to i64
290  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
291  %array.i = load i32, i32* %array.i.ptr, align 4
292  %loop.acc.next = add i32 %loop.acc, %array.i
293
294  %i.next = add nsw i32 %i, 1
295  %continue = icmp slt i32 %i.next, %n
296  br i1 %continue, label %loop, label %exit
297
298exit:
299  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
300  ret i32 %result
301}
302
303define i32 @signed_loop_start_to_n_both_checks(i32* %array, i32 %length, i32 %start, i32 %n) {
304; CHECK-LABEL: @signed_loop_start_to_n_both_checks
305entry:
306  %tmp5 = icmp sle i32 %n, 0
307  br i1 %tmp5, label %exit, label %loop.preheader
308
309loop.preheader:
310; CHECK: loop.preheader:
311; CHECK: [[lower_check:[^ ]+]] = icmp sge i32 %start, 0
312; CHECK-NEXT: [[start_1:[^ ]+]] = add i32 %start, 1
313; CHECK-NEXT: [[n_sgt_start_1:[^ ]+]] = icmp sgt i32 %n, [[start_1]]
314; CHECK-NEXT: [[smax:[^ ]+]] = select i1 [[n_sgt_start_1]], i32 %n, i32 [[start_1]]
315; CHECK-NEXT: [[max_index:[^ ]+]] = add i32 [[smax]], -1
316; CHECK-NEXT: [[upper_check:[^ ]+]] = icmp slt i32 [[max_index]], %length
317; CHECK-NEXT: br label %loop
318  br label %loop
319
320loop:
321; CHECK: loop:
322; CHECK: [[wide_cond:[^ ]+]] = and i1 [[lower_check]], [[upper_check]]
323; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
324  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
325  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
326  %within.bounds.1 = icmp slt i32 %i, %length
327  %within.bounds.2 = icmp sge i32 %i, 0
328  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
329  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
330
331  %i.i64 = zext i32 %i to i64
332  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
333  %array.i = load i32, i32* %array.i.ptr, align 4
334  %loop.acc.next = add i32 %loop.acc, %array.i
335
336  %i.next = add nsw i32 %i, 1
337  %continue = icmp slt i32 %i.next, %n
338  br i1 %continue, label %loop, label %exit
339
340exit:
341  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
342  ret i32 %result
343}
344
345define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
346; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition
347entry:
348  %tmp5 = icmp eq i32 %n, 0
349  br i1 %tmp5, label %exit, label %loop.preheader
350
351loop.preheader:
352; CHECK: loop.preheader:
353; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
354; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp ult i32 [[max_index]], %length
355; CHECK-NEXT: br label %loop
356  br label %loop
357
358loop:
359; CHECK: loop:
360; CHECK: %unrelated.cond = icmp ult i32 %x, %length
361; CHECK: [[guard_cond:[^ ]+]] = and i1 %unrelated.cond, [[wide_cond]]
362; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[guard_cond]], i32 9) [ "deopt"() ]
363  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
364  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
365  %within.bounds = icmp ult i32 %i, %length
366  %unrelated.cond = icmp ult i32 %x, %length
367  %guard.cond = and i1 %within.bounds, %unrelated.cond
368  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
369
370  %i.i64 = zext i32 %i to i64
371  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
372  %array.i = load i32, i32* %array.i.ptr, align 4
373  %loop.acc.next = add i32 %loop.acc, %array.i
374
375  %i.next = add nuw i32 %i, 1
376  %continue = icmp ult i32 %i.next, %n
377  br i1 %continue, label %loop, label %exit
378
379exit:
380  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
381  ret i32 %result
382}
383
384; Don't change the guard condition if there were no widened subconditions
385define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
386; CHECK-LABEL: @test_no_widened_conditions
387entry:
388  %tmp5 = icmp eq i32 %n, 0
389  br i1 %tmp5, label %exit, label %loop.preheader
390
391loop.preheader:
392; CHECK: loop.preheader:
393; CHECK-NEXT: br label %loop
394  br label %loop
395
396loop:
397; CHECK: loop:
398; CHECK: %unrelated.cond.1 = icmp eq i32 %x1, %i
399; CHECK-NEXT: %unrelated.cond.2 = icmp eq i32 %x2, %i
400; CHECK-NEXT: %unrelated.cond.3 = icmp eq i32 %x3, %i
401; CHECK-NEXT: %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
402; CHECK-NEXT: %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
403; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
404  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
405  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
406  %unrelated.cond.1 = icmp eq i32 %x1, %i
407  %unrelated.cond.2 = icmp eq i32 %x2, %i
408  %unrelated.cond.3 = icmp eq i32 %x3, %i
409  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
410  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
411
412  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
413
414  %i.i64 = zext i32 %i to i64
415  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
416  %array.i = load i32, i32* %array.i.ptr, align 4
417  %loop.acc.next = add i32 %loop.acc, %array.i
418
419  %i.next = add nuw i32 %i, 1
420  %continue = icmp ult i32 %i.next, %n
421  br i1 %continue, label %loop, label %exit
422
423exit:
424  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
425  ret i32 %result
426}
427
428define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
429; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound
430entry:
431  %tmp5 = icmp sle i32 %n, 0
432  br i1 %tmp5, label %exit, label %loop.preheader
433
434loop.preheader:
435; CHECK: loop.preheader:
436; CHECK-NEXT: br label %loop
437  br label %loop
438
439loop:
440; CHECK: loop:
441; CHECK: %bound = add i32 %i, %x
442; CHECK-NEXT: %within.bounds = icmp slt i32 %i, %bound
443; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
444  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
445  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
446  %bound = add i32 %i, %x
447  %within.bounds = icmp slt i32 %i, %bound
448  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
449
450  %i.i64 = zext i32 %i to i64
451  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
452  %array.i = load i32, i32* %array.i.ptr, align 4
453  %loop.acc.next = add i32 %loop.acc, %array.i
454
455  %i.next = add nsw i32 %i, 1
456  %continue = icmp slt i32 %i.next, %n
457  br i1 %continue, label %loop, label %exit
458
459exit:
460  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
461  ret i32 %result
462}
463
464define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
465; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate
466entry:
467  %tmp5 = icmp sle i32 %n, 0
468  br i1 %tmp5, label %exit, label %loop.preheader
469
470loop.preheader:
471; CHECK: loop.preheader:
472; CHECK-NEXT: br label %loop
473  br label %loop
474
475loop:
476; CHECK: loop:
477; CHECK: %guard.cond = icmp eq i32 %i, %x
478; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
479  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
480  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
481  %guard.cond = icmp eq i32 %i, %x
482  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
483
484  %i.i64 = zext i32 %i to i64
485  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
486  %array.i = load i32, i32* %array.i.ptr, align 4
487  %loop.acc.next = add i32 %loop.acc, %array.i
488
489  %i.next = add nsw i32 %i, 1
490  %continue = icmp slt i32 %i.next, %n
491  br i1 %continue, label %loop, label %exit
492
493exit:
494  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
495  ret i32 %result
496}
497
498define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
499; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length
500entry:
501  %tmp5 = icmp eq i32 %n, 0
502  br i1 %tmp5, label %exit, label %loop.preheader
503
504loop.preheader:
505; CHECK: loop.preheader:
506; CHECK: [[max_index:[^ ]+]] = add i32 %n, -1
507; CHECK-NEXT: [[length:[^ ]+]] = zext i16 %length.i16 to i32
508; CHECK-NEXT: [[wide_cond:[^ ]+]] = icmp ult i32 [[max_index]], [[length]]
509; CHECK-NEXT: br label %loop
510  br label %loop
511
512loop:
513; CHECK: loop:
514; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
515  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
516  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
517  %length = zext i16 %length.i16 to i32
518  %within.bounds = icmp ult i32 %i, %length
519  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
520
521  %i.i64 = zext i32 %i to i64
522  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
523  %array.i = load i32, i32* %array.i.ptr, align 4
524  %loop.acc.next = add i32 %loop.acc, %array.i
525
526  %i.next = add nuw i32 %i, 1
527  %continue = icmp ult i32 %i.next, %n
528  br i1 %continue, label %loop, label %exit
529
530exit:
531  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
532  ret i32 %result
533}
534
535define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
536; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length
537entry:
538  %tmp5 = icmp eq i32 %n, 0
539  br i1 %tmp5, label %exit, label %loop.preheader
540
541loop.preheader:
542; CHECK: loop.preheader:
543; CHECK-NEXT: br label %loop
544  br label %loop
545
546loop:
547; CHECK: loop:
548; CHECK-NEXT: %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
549; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
550; CHECK-NEXT: %length.udiv = udiv i32 %length, %divider
551; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %length.udiv
552; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
553  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
554  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
555  %length.udiv = udiv i32 %length, %divider
556  %within.bounds = icmp ult i32 %i, %length.udiv
557  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
558
559  %i.i64 = zext i32 %i to i64
560  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
561  %array.i = load i32, i32* %array.i.ptr, align 4
562  %loop.acc.next = add i32 %loop.acc, %array.i
563
564  %i.next = add nuw i32 %i, 1
565  %continue = icmp ult i32 %i.next, %n
566  br i1 %continue, label %loop, label %exit
567
568exit:
569  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
570  ret i32 %result
571}
572