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: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
15; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
16; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
17; CHECK-NEXT: br label %loop
18  br label %loop
19
20loop:
21; CHECK: loop:
22; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
23  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
24  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
25  %within.bounds = icmp ult i32 %i, %length
26  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
27
28  %i.i64 = zext i32 %i to i64
29  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
30  %array.i = load i32, i32* %array.i.ptr, align 4
31  %loop.acc.next = add i32 %loop.acc, %array.i
32
33  %i.next = add nuw i32 %i, 1
34  %continue = icmp ult i32 %i.next, %n
35  br i1 %continue, label %loop, label %exit
36
37exit:
38  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
39  ret i32 %result
40}
41
42define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) {
43; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check
44entry:
45  %tmp5 = icmp eq i32 %n, 0
46  br i1 %tmp5, label %exit, label %loop.preheader
47
48loop.preheader:
49; CHECK: loop.preheader:
50; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
51; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ult i32 %n, %length
52; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
53; CHECK-NEXT: br label %loop
54  br label %loop
55
56loop:
57; CHECK: loop:
58; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
59  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
60  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
61  %within.bounds = icmp ult i32 %i, %length
62  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
63
64  %i.i64 = zext i32 %i to i64
65  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
66  %array.i = load i32, i32* %array.i.ptr, align 4
67  %loop.acc.next = add i32 %loop.acc, %array.i
68
69  %i.next = add nuw i32 %i, 1
70  %continue = icmp ule i32 %i.next, %n
71  br i1 %continue, label %loop, label %exit
72
73exit:
74  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
75  ret i32 %result
76}
77
78define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) {
79; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check
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: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
87; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
88; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
89; CHECK-NEXT: br label %loop
90  br label %loop
91
92loop:
93; CHECK: loop:
94; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
95  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
96  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
97  %within.bounds = icmp ugt i32 %length, %i
98  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
99
100  %i.i64 = zext i32 %i to i64
101  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
102  %array.i = load i32, i32* %array.i.ptr, align 4
103  %loop.acc.next = add i32 %loop.acc, %array.i
104
105  %i.next = add nuw i32 %i, 1
106  %continue = icmp ult i32 %i.next, %n
107  br i1 %continue, label %loop, label %exit
108
109exit:
110  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
111  ret i32 %result
112}
113
114define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
115; CHECK-LABEL: @signed_loop_0_to_n_ult_check
116entry:
117  %tmp5 = icmp sle i32 %n, 0
118  br i1 %tmp5, label %exit, label %loop.preheader
119
120loop.preheader:
121; CHECK: loop.preheader:
122; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
123; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
124; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
125; CHECK-NEXT: br label %loop
126  br label %loop
127
128loop:
129; CHECK: loop:
130; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
131  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
132  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
133  %within.bounds = icmp ult i32 %i, %length
134  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
135
136  %i.i64 = zext i32 %i to i64
137  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
138  %array.i = load i32, i32* %array.i.ptr, align 4
139  %loop.acc.next = add i32 %loop.acc, %array.i
140
141  %i.next = add nuw i32 %i, 1
142  %continue = icmp slt i32 %i.next, %n
143  br i1 %continue, label %loop, label %exit
144
145exit:
146  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
147  ret i32 %result
148}
149
150define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) {
151; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate
152entry:
153  %tmp5 = icmp sle i32 %n, 0
154  br i1 %tmp5, label %exit, label %loop.preheader
155
156loop.preheader:
157; CHECK: loop.preheader:
158; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
159; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length
160; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
161; CHECK-NEXT: br label %loop
162  br label %loop
163
164loop:
165; CHECK: loop:
166; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
167  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
168  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
169  %within.bounds = icmp ult i32 %i, %length
170  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
171
172  %i.i64 = zext i32 %i to i64
173  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
174  %array.i = load i32, i32* %array.i.ptr, align 4
175  %loop.acc.next = add i32 %loop.acc, %array.i
176
177  %i.next = add nuw i32 %i, 1
178  %continue = icmp sgt i32 %i.next, %n
179  br i1 %continue, label %exit, label %loop
180
181exit:
182  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
183  ret i32 %result
184}
185
186define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) {
187; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check
188entry:
189  %tmp5 = icmp sle i32 %n, 0
190  br i1 %tmp5, label %exit, label %loop.preheader
191
192loop.preheader:
193; CHECK: loop.preheader:
194; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
195; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length
196; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
197; CHECK-NEXT: br label %loop
198  br label %loop
199
200loop:
201; CHECK: loop:
202; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
203  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
204  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
205  %within.bounds = icmp ult i32 %i, %length
206  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
207
208  %i.i64 = zext i32 %i to i64
209  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
210  %array.i = load i32, i32* %array.i.ptr, align 4
211  %loop.acc.next = add i32 %loop.acc, %array.i
212
213  %i.next = add nuw i32 %i, 1
214  %continue = icmp sle i32 %i.next, %n
215  br i1 %continue, label %loop, label %exit
216
217exit:
218  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
219  ret i32 %result
220}
221
222define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
223; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n
224entry:
225  %tmp5 = icmp sle i32 %n, 0
226  br i1 %tmp5, label %exit, label %loop.preheader
227
228loop.preheader:
229; CHECK: loop.preheader:
230; CHECK-NEXT: br label %loop
231  br label %loop
232
233loop:
234; CHECK: loop:
235; CHECK: %within.bounds = icmp ult i32 %i, %length
236; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
237  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
238  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
239  %within.bounds = icmp ult i32 %i, %length
240  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
241
242  %i.i64 = zext i32 %i to i64
243  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
244  %array.i = load i32, i32* %array.i.ptr, align 4
245  %loop.acc.next = add i32 %loop.acc, %array.i
246
247  %i.next = add nsw i32 %i, 1
248  %continue = icmp ne i32 %i.next, %n
249  br i1 %continue, label %loop, label %exit
250
251exit:
252  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
253  ret i32 %result
254}
255
256define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
257; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step
258entry:
259  %tmp5 = icmp sle i32 %n, 0
260  br i1 %tmp5, label %exit, label %loop.preheader
261
262loop.preheader:
263; CHECK: loop.preheader:
264; CHECK-NEXT: br label %loop
265  br label %loop
266
267loop:
268; CHECK: loop:
269; CHECK: %within.bounds = icmp ult i32 %i, %length
270; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
271  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
272  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
273  %within.bounds = icmp ult i32 %i, %length
274  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
275
276  %i.i64 = zext i32 %i to i64
277  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
278  %array.i = load i32, i32* %array.i.ptr, align 4
279  %loop.acc.next = add i32 %loop.acc, %array.i
280
281  %i.next = add nsw i32 %i, 2
282  %continue = icmp slt i32 %i.next, %n
283  br i1 %continue, label %loop, label %exit
284
285exit:
286  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
287  ret i32 %result
288}
289
290define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
291; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check
292entry:
293  %tmp5 = icmp sle i32 %n, 0
294  br i1 %tmp5, label %exit, label %loop.preheader
295
296loop.preheader:
297; CHECK: loop.preheader:
298; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
299; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
300; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
301; CHECK-NEXT: br label %loop
302  br label %loop
303
304loop:
305; CHECK: loop:
306; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
307  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
308  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
309  %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
310
311  %within.bounds = icmp ult i32 %j, %length
312  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
313
314  %i.i64 = zext i32 %i to i64
315  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
316  %array.i = load i32, i32* %array.i.ptr, align 4
317  %loop.acc.next = add i32 %loop.acc, %array.i
318
319  %j.next = add nsw i32 %j, 1
320  %i.next = add nsw i32 %i, 1
321  %continue = icmp slt i32 %i.next, %n
322  br i1 %continue, label %loop, label %exit
323
324exit:
325  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
326  ret i32 %result
327}
328
329define i32 @signed_loop_0_to_n_unrelated_iv_range_check(i32* %array, i32 %start, i32 %length, i32 %n) {
330; CHECK-LABEL: @signed_loop_0_to_n_unrelated_iv_range_check
331entry:
332  %tmp5 = icmp sle i32 %n, 0
333  br i1 %tmp5, label %exit, label %loop.preheader
334
335loop.preheader:
336; CHECK: loop.preheader:
337; CHECK-NEXT: br label %loop
338  br label %loop
339
340loop:
341; CHECK: loop:
342; CHECK: %within.bounds = icmp ult i32 %j, %length
343; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
344  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
345  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
346  %j = phi i32 [ %j.next, %loop ], [ %start, %loop.preheader ]
347
348  %within.bounds = icmp ult i32 %j, %length
349  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
350
351  %i.i64 = zext i32 %i to i64
352  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
353  %array.i = load i32, i32* %array.i.ptr, align 4
354  %loop.acc.next = add i32 %loop.acc, %array.i
355
356  %j.next = add nsw i32 %j, 1
357  %i.next = add nsw i32 %i, 1
358  %continue = icmp slt i32 %i.next, %n
359  br i1 %continue, label %loop, label %exit
360
361exit:
362  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
363  ret i32 %result
364}
365
366define i32 @two_range_checks(i32* %array.1, i32 %length.1,
367                             i32* %array.2, i32 %length.2, i32 %n) {
368; CHECK-LABEL: @two_range_checks
369entry:
370  %tmp5 = icmp eq i32 %n, 0
371  br i1 %tmp5, label %exit, label %loop.preheader
372
373loop.preheader:
374; CHECK: loop.preheader:
375; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
376; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
377; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
378; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
379; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
380; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
381; CHECK-NEXT: br label %loop
382  br label %loop
383
384loop:
385; CHECK: loop:
386; CHECK: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
387; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
388  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
389  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
390  %within.bounds.1 = icmp ult i32 %i, %length.1
391  %within.bounds.2 = icmp ult i32 %i, %length.2
392  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
393  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
394
395  %i.i64 = zext i32 %i to i64
396  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
397  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
398  %loop.acc.1 = add i32 %loop.acc, %array.1.i
399
400  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
401  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
402  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
403
404  %i.next = add nuw i32 %i, 1
405  %continue = icmp ult i32 %i.next, %n
406  br i1 %continue, label %loop, label %exit
407
408exit:
409  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
410  ret i32 %result
411}
412
413define i32 @three_range_checks(i32* %array.1, i32 %length.1,
414                               i32* %array.2, i32 %length.2,
415                               i32* %array.3, i32 %length.3, i32 %n) {
416; CHECK-LABEL: @three_range_checks
417entry:
418  %tmp5 = icmp eq i32 %n, 0
419  br i1 %tmp5, label %exit, label %loop.preheader
420
421loop.preheader:
422; CHECK: loop.preheader:
423; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
424; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
425; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
426; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
427; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
428; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
429; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
430; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
431; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
432; CHECK-NEXT: br label %loop
433  br label %loop
434
435loop:
436; CHECK: loop:
437; CHECK: [[wide_cond_and:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
438; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_and]], [[wide_cond_3]]
439; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
440  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
441  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
442  %within.bounds.1 = icmp ult i32 %i, %length.1
443  %within.bounds.2 = icmp ult i32 %i, %length.2
444  %within.bounds.3 = icmp ult i32 %i, %length.3
445  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
446  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
447  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
448
449  %i.i64 = zext i32 %i to i64
450  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
451  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
452  %loop.acc.1 = add i32 %loop.acc, %array.1.i
453
454  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
455  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
456  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
457
458  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
459  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
460  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
461
462  %i.next = add nuw i32 %i, 1
463  %continue = icmp ult i32 %i.next, %n
464  br i1 %continue, label %loop, label %exit
465
466exit:
467  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
468  ret i32 %result
469}
470
471define i32 @three_guards(i32* %array.1, i32 %length.1,
472                         i32* %array.2, i32 %length.2,
473                         i32* %array.3, i32 %length.3, i32 %n) {
474; CHECK-LABEL: @three_guards
475entry:
476  %tmp5 = icmp eq i32 %n, 0
477  br i1 %tmp5, label %exit, label %loop.preheader
478
479loop.preheader:
480; CHECK: loop.preheader:
481; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
482; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
483; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
484; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
485; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
486; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
487; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
488; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
489; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
490; CHECK-NEXT: br label %loop
491  br label %loop
492
493loop:
494; CHECK: loop:
495; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_1]], i32 9) [ "deopt"() ]
496; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_2]], i32 9) [ "deopt"() ]
497; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_3]], i32 9) [ "deopt"() ]
498
499  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
500  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
501
502  %within.bounds.1 = icmp ult i32 %i, %length.1
503  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
504
505  %i.i64 = zext i32 %i to i64
506  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
507  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
508  %loop.acc.1 = add i32 %loop.acc, %array.1.i
509
510  %within.bounds.2 = icmp ult i32 %i, %length.2
511  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
512
513  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
514  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
515  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
516
517  %within.bounds.3 = icmp ult i32 %i, %length.3
518  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
519
520  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
521  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
522  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
523
524  %i.next = add nuw i32 %i, 1
525  %continue = icmp ult i32 %i.next, %n
526  br i1 %continue, label %loop, label %exit
527
528exit:
529  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
530  ret i32 %result
531}
532
533define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
534; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition
535entry:
536  %tmp5 = icmp eq i32 %n, 0
537  br i1 %tmp5, label %exit, label %loop.preheader
538
539loop.preheader:
540; CHECK: loop.preheader:
541; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
542; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
543; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
544; CHECK-NEXT: br label %loop
545  br label %loop
546
547loop:
548; CHECK: loop:
549; CHECK: %unrelated.cond = icmp ult i32 %x, %length
550; CHECK: [[guard_cond:[^ ]+]] = and i1 %unrelated.cond, [[wide_cond]]
551; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[guard_cond]], i32 9) [ "deopt"() ]
552  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
553  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
554  %within.bounds = icmp ult i32 %i, %length
555  %unrelated.cond = icmp ult i32 %x, %length
556  %guard.cond = and i1 %within.bounds, %unrelated.cond
557  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, 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
573; Don't change the guard condition if there were no widened subconditions
574define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
575; CHECK-LABEL: @test_no_widened_conditions
576entry:
577  %tmp5 = icmp eq i32 %n, 0
578  br i1 %tmp5, label %exit, label %loop.preheader
579
580loop.preheader:
581; CHECK: loop.preheader:
582; CHECK-NEXT: br label %loop
583  br label %loop
584
585loop:
586; CHECK: loop:
587; CHECK: %unrelated.cond.1 = icmp eq i32 %x1, %i
588; CHECK-NEXT: %unrelated.cond.2 = icmp eq i32 %x2, %i
589; CHECK-NEXT: %unrelated.cond.3 = icmp eq i32 %x3, %i
590; CHECK-NEXT: %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
591; CHECK-NEXT: %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
592; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
593  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
594  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
595  %unrelated.cond.1 = icmp eq i32 %x1, %i
596  %unrelated.cond.2 = icmp eq i32 %x2, %i
597  %unrelated.cond.3 = icmp eq i32 %x3, %i
598  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
599  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
600
601  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
602
603  %i.i64 = zext i32 %i to i64
604  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
605  %array.i = load i32, i32* %array.i.ptr, align 4
606  %loop.acc.next = add i32 %loop.acc, %array.i
607
608  %i.next = add nuw i32 %i, 1
609  %continue = icmp ult i32 %i.next, %n
610  br i1 %continue, label %loop, label %exit
611
612exit:
613  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
614  ret i32 %result
615}
616
617define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
618; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound
619entry:
620  %tmp5 = icmp sle i32 %n, 0
621  br i1 %tmp5, label %exit, label %loop.preheader
622
623loop.preheader:
624; CHECK: loop.preheader:
625; CHECK-NEXT: br label %loop
626  br label %loop
627
628loop:
629; CHECK: loop:
630; CHECK: %bound = add i32 %i, %x
631; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %bound
632; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
633  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
634  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
635  %bound = add i32 %i, %x
636  %within.bounds = icmp ult i32 %i, %bound
637  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
638
639  %i.i64 = zext i32 %i to i64
640  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
641  %array.i = load i32, i32* %array.i.ptr, align 4
642  %loop.acc.next = add i32 %loop.acc, %array.i
643
644  %i.next = add nsw i32 %i, 1
645  %continue = icmp slt i32 %i.next, %n
646  br i1 %continue, label %loop, label %exit
647
648exit:
649  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
650  ret i32 %result
651}
652
653define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
654; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate
655entry:
656  %tmp5 = icmp sle i32 %n, 0
657  br i1 %tmp5, label %exit, label %loop.preheader
658
659loop.preheader:
660; CHECK: loop.preheader:
661; CHECK-NEXT: br label %loop
662  br label %loop
663
664loop:
665; CHECK: loop:
666; CHECK: %guard.cond = icmp eq i32 %i, %x
667; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
668  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
669  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
670  %guard.cond = icmp eq i32 %i, %x
671  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
672
673  %i.i64 = zext i32 %i to i64
674  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
675  %array.i = load i32, i32* %array.i.ptr, align 4
676  %loop.acc.next = add i32 %loop.acc, %array.i
677
678  %i.next = add nsw i32 %i, 1
679  %continue = icmp slt i32 %i.next, %n
680  br i1 %continue, label %loop, label %exit
681
682exit:
683  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
684  ret i32 %result
685}
686
687define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
688; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length
689entry:
690  %tmp5 = icmp eq i32 %n, 0
691  br i1 %tmp5, label %exit, label %loop.preheader
692
693loop.preheader:
694; CHECK: loop.preheader:
695; CHECK: [[length:[^ ]+]] = zext i16 %length.i16 to i32
696; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, [[length]]
697; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, [[length]]
698; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
699; CHECK-NEXT: br label %loop
700  br label %loop
701
702loop:
703; CHECK: loop:
704; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
705  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
706  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
707  %length = zext i16 %length.i16 to i32
708  %within.bounds = icmp ult i32 %i, %length
709  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
710
711  %i.i64 = zext i32 %i to i64
712  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
713  %array.i = load i32, i32* %array.i.ptr, align 4
714  %loop.acc.next = add i32 %loop.acc, %array.i
715
716  %i.next = add nuw i32 %i, 1
717  %continue = icmp ult i32 %i.next, %n
718  br i1 %continue, label %loop, label %exit
719
720exit:
721  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
722  ret i32 %result
723}
724
725define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
726; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length
727entry:
728  %tmp5 = icmp eq i32 %n, 0
729  br i1 %tmp5, label %exit, label %loop.preheader
730
731loop.preheader:
732; CHECK: loop.preheader:
733; CHECK-NEXT: br label %loop
734  br label %loop
735
736loop:
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: %length.udiv = udiv i32 %length, %divider
741; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %length.udiv
742; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
743  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
744  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
745  %length.udiv = udiv i32 %length, %divider
746  %within.bounds = icmp ult i32 %i, %length.udiv
747  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
748
749  %i.i64 = zext i32 %i to i64
750  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
751  %array.i = load i32, i32* %array.i.ptr, align 4
752  %loop.acc.next = add i32 %loop.acc, %array.i
753
754  %i.next = add nuw i32 %i, 1
755  %continue = icmp ult i32 %i.next, %n
756  br i1 %continue, label %loop, label %exit
757
758exit:
759  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
760  ret i32 %result
761}
762