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: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
15; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %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: [[limit_check:[^ ]+]] = icmp ult i32 %n, %length
51; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %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: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
87; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %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: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
123; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %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_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) {
151; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known
152entry:
153  %tmp5 = icmp sle i32 %n, 0
154  %length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648}
155  br i1 %tmp5, label %exit, label %loop.preheader
156
157loop.preheader:
158; CHECK: loop.preheader:
159; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
160; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 true, [[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 slt i32 %i.next, %n
179  br i1 %continue, label %loop, label %exit
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_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) {
187; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate
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: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length
195; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %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 sgt i32 %i.next, %n
215  br i1 %continue, label %exit, label %loop
216
217exit:
218  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
219  ret i32 %result
220}
221
222define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) {
223; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check
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: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length
231; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
232; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
233; CHECK-NEXT: br label %loop
234  br label %loop
235
236loop:
237; CHECK: loop:
238; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
239  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
240  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
241  %within.bounds = icmp ult i32 %i, %length
242  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
243
244  %i.i64 = zext i32 %i to i64
245  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
246  %array.i = load i32, i32* %array.i.ptr, align 4
247  %loop.acc.next = add i32 %loop.acc, %array.i
248
249  %i.next = add nuw i32 %i, 1
250  %continue = icmp sle i32 %i.next, %n
251  br i1 %continue, label %loop, label %exit
252
253exit:
254  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
255  ret i32 %result
256}
257
258define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
259; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n
260entry:
261  %tmp5 = icmp sle i32 %n, 0
262  br i1 %tmp5, label %exit, label %loop.preheader
263
264loop.preheader:
265; CHECK: loop.preheader:
266; CHECK-NEXT: br label %loop
267  br label %loop
268
269loop:
270; CHECK: loop:
271; CHECK: %within.bounds = icmp ult i32 %i, %length
272; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
273  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
274  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
275  %within.bounds = icmp ult i32 %i, %length
276  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
277
278  %i.i64 = zext i32 %i to i64
279  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
280  %array.i = load i32, i32* %array.i.ptr, align 4
281  %loop.acc.next = add i32 %loop.acc, %array.i
282
283  %i.next = add nsw i32 %i, 1
284  %continue = icmp ne i32 %i.next, %n
285  br i1 %continue, label %loop, label %exit
286
287exit:
288  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
289  ret i32 %result
290}
291
292define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
293; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step
294entry:
295  %tmp5 = icmp sle i32 %n, 0
296  br i1 %tmp5, label %exit, label %loop.preheader
297
298loop.preheader:
299; CHECK: loop.preheader:
300; CHECK-NEXT: br label %loop
301  br label %loop
302
303loop:
304; CHECK: loop:
305; CHECK: %within.bounds = icmp ult i32 %i, %length
306; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, 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  %within.bounds = icmp ult i32 %i, %length
310  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
311
312  %i.i64 = zext i32 %i to i64
313  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
314  %array.i = load i32, i32* %array.i.ptr, align 4
315  %loop.acc.next = add i32 %loop.acc, %array.i
316
317  %i.next = add nsw i32 %i, 2
318  %continue = icmp slt i32 %i.next, %n
319  br i1 %continue, label %loop, label %exit
320
321exit:
322  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
323  ret i32 %result
324}
325
326define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
327; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check
328entry:
329  %tmp5 = icmp sle i32 %n, 0
330  br i1 %tmp5, label %exit, label %loop.preheader
331
332loop.preheader:
333; CHECK: loop.preheader:
334; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
335; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
336; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
337; CHECK-NEXT: br label %loop
338  br label %loop
339
340loop:
341; CHECK: loop:
342; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
343  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
344  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
345  %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
346
347  %within.bounds = icmp ult i32 %j, %length
348  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
349
350  %i.i64 = zext i32 %i to i64
351  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
352  %array.i = load i32, i32* %array.i.ptr, align 4
353  %loop.acc.next = add i32 %loop.acc, %array.i
354
355  %j.next = add nsw i32 %j, 1
356  %i.next = add nsw i32 %i, 1
357  %continue = icmp slt i32 %i.next, %n
358  br i1 %continue, label %loop, label %exit
359
360exit:
361  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
362  ret i32 %result
363}
364
365define i32 @signed_loop_0_to_n_unrelated_iv_range_check(i32* %array, i32 %start, i32 %length, i32 %n) {
366; CHECK-LABEL: @signed_loop_0_to_n_unrelated_iv_range_check
367entry:
368  %tmp5 = icmp sle i32 %n, 0
369  br i1 %tmp5, label %exit, label %loop.preheader
370
371loop.preheader:
372; CHECK: loop.preheader:
373; CHECK-NEXT: br label %loop
374  br label %loop
375
376loop:
377; CHECK: loop:
378; CHECK: %within.bounds = icmp ult i32 %j, %length
379; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
380  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
381  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
382  %j = phi i32 [ %j.next, %loop ], [ %start, %loop.preheader ]
383
384  %within.bounds = icmp ult i32 %j, %length
385  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
386
387  %i.i64 = zext i32 %i to i64
388  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
389  %array.i = load i32, i32* %array.i.ptr, align 4
390  %loop.acc.next = add i32 %loop.acc, %array.i
391
392  %j.next = add nsw i32 %j, 1
393  %i.next = add nsw i32 %i, 1
394  %continue = icmp slt i32 %i.next, %n
395  br i1 %continue, label %loop, label %exit
396
397exit:
398  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
399  ret i32 %result
400}
401
402define i32 @two_range_checks(i32* %array.1, i32 %length.1,
403                             i32* %array.2, i32 %length.2, i32 %n) {
404; CHECK-LABEL: @two_range_checks
405entry:
406  %tmp5 = icmp eq i32 %n, 0
407  br i1 %tmp5, label %exit, label %loop.preheader
408
409loop.preheader:
410; CHECK: loop.preheader:
411; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
412; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
413; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
414; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
415; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
416; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
417; CHECK-NEXT: br label %loop
418  br label %loop
419
420loop:
421; CHECK: loop:
422; CHECK: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
423; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
424  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
425  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
426  %within.bounds.1 = icmp ult i32 %i, %length.1
427  %within.bounds.2 = icmp ult i32 %i, %length.2
428  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
429  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
430
431  %i.i64 = zext i32 %i to i64
432  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
433  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
434  %loop.acc.1 = add i32 %loop.acc, %array.1.i
435
436  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
437  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
438  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
439
440  %i.next = add nuw i32 %i, 1
441  %continue = icmp ult i32 %i.next, %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 @three_range_checks(i32* %array.1, i32 %length.1,
450                               i32* %array.2, i32 %length.2,
451                               i32* %array.3, i32 %length.3, i32 %n) {
452; CHECK-LABEL: @three_range_checks
453entry:
454  %tmp5 = icmp eq i32 %n, 0
455  br i1 %tmp5, label %exit, label %loop.preheader
456
457loop.preheader:
458; CHECK: loop.preheader:
459; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
460; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
461; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
462; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
463; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
464; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
465; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
466; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
467; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
468; CHECK-NEXT: br label %loop
469  br label %loop
470
471loop:
472; CHECK: loop:
473; CHECK: [[wide_cond_and:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
474; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_and]], [[wide_cond_3]]
475; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
476  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
477  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
478  %within.bounds.1 = icmp ult i32 %i, %length.1
479  %within.bounds.2 = icmp ult i32 %i, %length.2
480  %within.bounds.3 = icmp ult i32 %i, %length.3
481  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
482  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
483  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
484
485  %i.i64 = zext i32 %i to i64
486  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
487  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
488  %loop.acc.1 = add i32 %loop.acc, %array.1.i
489
490  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
491  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
492  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
493
494  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
495  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
496  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
497
498  %i.next = add nuw i32 %i, 1
499  %continue = icmp ult i32 %i.next, %n
500  br i1 %continue, label %loop, label %exit
501
502exit:
503  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
504  ret i32 %result
505}
506
507define i32 @three_guards(i32* %array.1, i32 %length.1,
508                         i32* %array.2, i32 %length.2,
509                         i32* %array.3, i32 %length.3, i32 %n) {
510; CHECK-LABEL: @three_guards
511entry:
512  %tmp5 = icmp eq i32 %n, 0
513  br i1 %tmp5, label %exit, label %loop.preheader
514
515loop.preheader:
516; CHECK: loop.preheader:
517; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
518; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
519; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
520; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
521; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
522; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
523; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
524; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
525; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
526; CHECK-NEXT: br label %loop
527  br label %loop
528
529loop:
530; CHECK: loop:
531; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_1]], i32 9) [ "deopt"() ]
532; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_2]], i32 9) [ "deopt"() ]
533; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_3]], i32 9) [ "deopt"() ]
534
535  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
536  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
537
538  %within.bounds.1 = icmp ult i32 %i, %length.1
539  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
540
541  %i.i64 = zext i32 %i to i64
542  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
543  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
544  %loop.acc.1 = add i32 %loop.acc, %array.1.i
545
546  %within.bounds.2 = icmp ult i32 %i, %length.2
547  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
548
549  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
550  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
551  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
552
553  %within.bounds.3 = icmp ult i32 %i, %length.3
554  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
555
556  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
557  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
558  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
559
560  %i.next = add nuw i32 %i, 1
561  %continue = icmp ult i32 %i.next, %n
562  br i1 %continue, label %loop, label %exit
563
564exit:
565  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
566  ret i32 %result
567}
568
569define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
570; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition
571entry:
572  %tmp5 = icmp eq i32 %n, 0
573  br i1 %tmp5, label %exit, label %loop.preheader
574
575loop.preheader:
576; CHECK: loop.preheader:
577; CHECK: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
578; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
579; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
580; CHECK-NEXT: br label %loop
581  br label %loop
582
583loop:
584; CHECK: loop:
585; CHECK: %unrelated.cond = icmp ult i32 %x, %length
586; CHECK: [[guard_cond:[^ ]+]] = and i1 %unrelated.cond, [[wide_cond]]
587; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[guard_cond]], i32 9) [ "deopt"() ]
588  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
589  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
590  %within.bounds = icmp ult i32 %i, %length
591  %unrelated.cond = icmp ult i32 %x, %length
592  %guard.cond = and i1 %within.bounds, %unrelated.cond
593  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
594
595  %i.i64 = zext i32 %i to i64
596  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
597  %array.i = load i32, i32* %array.i.ptr, align 4
598  %loop.acc.next = add i32 %loop.acc, %array.i
599
600  %i.next = add nuw i32 %i, 1
601  %continue = icmp ult i32 %i.next, %n
602  br i1 %continue, label %loop, label %exit
603
604exit:
605  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
606  ret i32 %result
607}
608
609; Don't change the guard condition if there were no widened subconditions
610define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
611; CHECK-LABEL: @test_no_widened_conditions
612entry:
613  %tmp5 = icmp eq i32 %n, 0
614  br i1 %tmp5, label %exit, label %loop.preheader
615
616loop.preheader:
617; CHECK: loop.preheader:
618; CHECK-NEXT: br label %loop
619  br label %loop
620
621loop:
622; CHECK: loop:
623; CHECK: %unrelated.cond.1 = icmp eq i32 %x1, %i
624; CHECK-NEXT: %unrelated.cond.2 = icmp eq i32 %x2, %i
625; CHECK-NEXT: %unrelated.cond.3 = icmp eq i32 %x3, %i
626; CHECK-NEXT: %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
627; CHECK-NEXT: %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
628; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
629  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
630  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
631  %unrelated.cond.1 = icmp eq i32 %x1, %i
632  %unrelated.cond.2 = icmp eq i32 %x2, %i
633  %unrelated.cond.3 = icmp eq i32 %x3, %i
634  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
635  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
636
637  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, 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 nuw i32 %i, 1
645  %continue = icmp ult 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_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
654; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound
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: %bound = add i32 %i, %x
667; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %bound
668; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
669  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
670  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
671  %bound = add i32 %i, %x
672  %within.bounds = icmp ult i32 %i, %bound
673  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
674
675  %i.i64 = zext i32 %i to i64
676  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
677  %array.i = load i32, i32* %array.i.ptr, align 4
678  %loop.acc.next = add i32 %loop.acc, %array.i
679
680  %i.next = add nsw i32 %i, 1
681  %continue = icmp slt i32 %i.next, %n
682  br i1 %continue, label %loop, label %exit
683
684exit:
685  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
686  ret i32 %result
687}
688
689define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
690; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate
691entry:
692  %tmp5 = icmp sle i32 %n, 0
693  br i1 %tmp5, label %exit, label %loop.preheader
694
695loop.preheader:
696; CHECK: loop.preheader:
697; CHECK-NEXT: br label %loop
698  br label %loop
699
700loop:
701; CHECK: loop:
702; CHECK: %guard.cond = icmp eq i32 %i, %x
703; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
704  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
705  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
706  %guard.cond = icmp eq i32 %i, %x
707  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
708
709  %i.i64 = zext i32 %i to i64
710  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
711  %array.i = load i32, i32* %array.i.ptr, align 4
712  %loop.acc.next = add i32 %loop.acc, %array.i
713
714  %i.next = add nsw i32 %i, 1
715  %continue = icmp slt i32 %i.next, %n
716  br i1 %continue, label %loop, label %exit
717
718exit:
719  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
720  ret i32 %result
721}
722
723define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
724; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length
725entry:
726  %tmp5 = icmp eq i32 %n, 0
727  br i1 %tmp5, label %exit, label %loop.preheader
728
729loop.preheader:
730; CHECK: loop.preheader:
731; CHECK: [[length:[^ ]+]] = zext i16 %length.i16 to i32
732; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, [[length]]
733; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, [[length]]
734; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
735; CHECK-NEXT: br label %loop
736  br label %loop
737
738loop:
739; CHECK: loop:
740; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
741  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
742  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
743  %length = zext i16 %length.i16 to i32
744  %within.bounds = icmp ult i32 %i, %length
745  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
746
747  %i.i64 = zext i32 %i to i64
748  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
749  %array.i = load i32, i32* %array.i.ptr, align 4
750  %loop.acc.next = add i32 %loop.acc, %array.i
751
752  %i.next = add nuw i32 %i, 1
753  %continue = icmp ult i32 %i.next, %n
754  br i1 %continue, label %loop, label %exit
755
756exit:
757  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
758  ret i32 %result
759}
760
761define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
762; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length
763entry:
764  %tmp5 = icmp eq i32 %n, 0
765  br i1 %tmp5, label %exit, label %loop.preheader
766
767loop.preheader:
768; CHECK: loop.preheader:
769; CHECK-NEXT: br label %loop
770  br label %loop
771
772loop:
773; CHECK: loop:
774; CHECK-NEXT: %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
775; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
776; CHECK-NEXT: %length.udiv = udiv i32 %length, %divider
777; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %length.udiv
778; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
779  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
780  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
781  %length.udiv = udiv i32 %length, %divider
782  %within.bounds = icmp ult i32 %i, %length.udiv
783  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
784
785  %i.i64 = zext i32 %i to i64
786  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
787  %array.i = load i32, i32* %array.i.ptr, align 4
788  %loop.acc.next = add i32 %loop.acc, %array.i
789
790  %i.next = add nuw i32 %i, 1
791  %continue = icmp ult i32 %i.next, %n
792  br i1 %continue, label %loop, label %exit
793
794exit:
795  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
796  ret i32 %result
797}
798