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_ugt_check(i32* %array, i32 %length, i32 %n) {
43; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_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 ule 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 ugt i32 %length, %i
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 ult 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 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
79; CHECK-LABEL: @signed_loop_0_to_n_ult_check
80entry:
81  %tmp5 = icmp sle 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 sle 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 ult i32 %i, %length
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 slt 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 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
115; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n
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-NEXT: br label %loop
123  br label %loop
124
125loop:
126; CHECK: loop:
127; CHECK: %within.bounds = icmp ult i32 %i, %length
128; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
129  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
130  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
131  %within.bounds = icmp ult i32 %i, %length
132  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
133
134  %i.i64 = zext i32 %i to i64
135  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
136  %array.i = load i32, i32* %array.i.ptr, align 4
137  %loop.acc.next = add i32 %loop.acc, %array.i
138
139  %i.next = add nsw i32 %i, 1
140  %continue = icmp ne i32 %i.next, %n
141  br i1 %continue, label %loop, label %exit
142
143exit:
144  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
145  ret i32 %result
146}
147
148define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
149; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step
150entry:
151  %tmp5 = icmp sle i32 %n, 0
152  br i1 %tmp5, label %exit, label %loop.preheader
153
154loop.preheader:
155; CHECK: loop.preheader:
156; CHECK-NEXT: br label %loop
157  br label %loop
158
159loop:
160; CHECK: loop:
161; CHECK: %within.bounds = icmp ult i32 %i, %length
162; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
163  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
164  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
165  %within.bounds = icmp ult i32 %i, %length
166  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
167
168  %i.i64 = zext i32 %i to i64
169  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
170  %array.i = load i32, i32* %array.i.ptr, align 4
171  %loop.acc.next = add i32 %loop.acc, %array.i
172
173  %i.next = add nsw i32 %i, 2
174  %continue = icmp slt i32 %i.next, %n
175  br i1 %continue, label %loop, label %exit
176
177exit:
178  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
179  ret i32 %result
180}
181
182define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
183; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check
184entry:
185  %tmp5 = icmp sle i32 %n, 0
186  br i1 %tmp5, label %exit, label %loop.preheader
187
188loop.preheader:
189; CHECK: loop.preheader:
190; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
191; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
192; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
193; CHECK-NEXT: br label %loop
194  br label %loop
195
196loop:
197; CHECK: loop:
198; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
199  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
200  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
201  %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
202
203  %within.bounds = icmp ult i32 %j, %length
204  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
205
206  %i.i64 = zext i32 %i to i64
207  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
208  %array.i = load i32, i32* %array.i.ptr, align 4
209  %loop.acc.next = add i32 %loop.acc, %array.i
210
211  %j.next = add nsw i32 %j, 1
212  %i.next = add nsw i32 %i, 1
213  %continue = icmp slt i32 %i.next, %n
214  br i1 %continue, label %loop, label %exit
215
216exit:
217  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
218  ret i32 %result
219}
220
221define i32 @signed_loop_0_to_n_unrelated_iv_range_check(i32* %array, i32 %start, i32 %length, i32 %n) {
222; CHECK-LABEL: @signed_loop_0_to_n_unrelated_iv_range_check
223entry:
224  %tmp5 = icmp sle i32 %n, 0
225  br i1 %tmp5, label %exit, label %loop.preheader
226
227loop.preheader:
228; CHECK: loop.preheader:
229; CHECK-NEXT: br label %loop
230  br label %loop
231
232loop:
233; CHECK: loop:
234; CHECK: %within.bounds = icmp ult i32 %j, %length
235; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
236  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
237  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
238  %j = phi i32 [ %j.next, %loop ], [ %start, %loop.preheader ]
239
240  %within.bounds = icmp ult i32 %j, %length
241  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
242
243  %i.i64 = zext i32 %i to i64
244  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
245  %array.i = load i32, i32* %array.i.ptr, align 4
246  %loop.acc.next = add i32 %loop.acc, %array.i
247
248  %j.next = add nsw i32 %j, 1
249  %i.next = add nsw i32 %i, 1
250  %continue = icmp slt 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 @two_range_checks(i32* %array.1, i32 %length.1,
259                             i32* %array.2, i32 %length.2, i32 %n) {
260; CHECK-LABEL: @two_range_checks
261entry:
262  %tmp5 = icmp eq i32 %n, 0
263  br i1 %tmp5, label %exit, label %loop.preheader
264
265loop.preheader:
266; CHECK: loop.preheader:
267; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
268; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
269; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
270; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2}}
271; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}}
272; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
273; CHECK-NEXT: br label %loop
274  br label %loop
275
276loop:
277; CHECK: loop:
278; CHECK: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
279; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
280  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
281  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
282  %within.bounds.1 = icmp ult i32 %i, %length.1
283  %within.bounds.2 = icmp ult i32 %i, %length.2
284  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
285  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
286
287  %i.i64 = zext i32 %i to i64
288  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
289  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
290  %loop.acc.1 = add i32 %loop.acc, %array.1.i
291
292  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
293  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
294  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
295
296  %i.next = add nuw i32 %i, 1
297  %continue = icmp ult i32 %i.next, %n
298  br i1 %continue, label %loop, label %exit
299
300exit:
301  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
302  ret i32 %result
303}
304
305define i32 @three_range_checks(i32* %array.1, i32 %length.1,
306                               i32* %array.2, i32 %length.2,
307                               i32* %array.3, i32 %length.3, i32 %n) {
308; CHECK-LABEL: @three_range_checks
309entry:
310  %tmp5 = icmp eq i32 %n, 0
311  br i1 %tmp5, label %exit, label %loop.preheader
312
313loop.preheader:
314; CHECK: loop.preheader:
315; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
316; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
317; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
318; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
319; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
320; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
321; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
322; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
323; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
324; CHECK-NEXT: br label %loop
325  br label %loop
326
327loop:
328; CHECK: loop:
329; CHECK: [[wide_cond_and:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]]
330; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_and]], [[wide_cond_3]]
331; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
332  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
333  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
334  %within.bounds.1 = icmp ult i32 %i, %length.1
335  %within.bounds.2 = icmp ult i32 %i, %length.2
336  %within.bounds.3 = icmp ult i32 %i, %length.3
337  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
338  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
339  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
340
341  %i.i64 = zext i32 %i to i64
342  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
343  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
344  %loop.acc.1 = add i32 %loop.acc, %array.1.i
345
346  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
347  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
348  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
349
350  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
351  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
352  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
353
354  %i.next = add nuw i32 %i, 1
355  %continue = icmp ult i32 %i.next, %n
356  br i1 %continue, label %loop, label %exit
357
358exit:
359  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
360  ret i32 %result
361}
362
363define i32 @three_guards(i32* %array.1, i32 %length.1,
364                         i32* %array.2, i32 %length.2,
365                         i32* %array.3, i32 %length.3, i32 %n) {
366; CHECK-LABEL: @three_guards
367entry:
368  %tmp5 = icmp eq i32 %n, 0
369  br i1 %tmp5, label %exit, label %loop.preheader
370
371loop.preheader:
372; CHECK: loop.preheader:
373; CHECK: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
374; CHECK-NEXT: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
375; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]]
376; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
377; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
378; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]]
379; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}}
380; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}}
381; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]]
382; CHECK-NEXT: br label %loop
383  br label %loop
384
385loop:
386; CHECK: loop:
387; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_1]], i32 9) [ "deopt"() ]
388; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_2]], i32 9) [ "deopt"() ]
389; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_3]], i32 9) [ "deopt"() ]
390
391  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
392  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
393
394  %within.bounds.1 = icmp ult i32 %i, %length.1
395  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
396
397  %i.i64 = zext i32 %i to i64
398  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
399  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
400  %loop.acc.1 = add i32 %loop.acc, %array.1.i
401
402  %within.bounds.2 = icmp ult i32 %i, %length.2
403  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
404
405  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
406  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
407  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
408
409  %within.bounds.3 = icmp ult i32 %i, %length.3
410  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
411
412  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
413  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
414  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
415
416  %i.next = add nuw i32 %i, 1
417  %continue = icmp ult i32 %i.next, %n
418  br i1 %continue, label %loop, label %exit
419
420exit:
421  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
422  ret i32 %result
423}
424
425define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
426; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition
427entry:
428  %tmp5 = icmp eq i32 %n, 0
429  br i1 %tmp5, label %exit, label %loop.preheader
430
431loop.preheader:
432; CHECK: loop.preheader:
433; CHECK: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
434; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length
435; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
436; CHECK-NEXT: br label %loop
437  br label %loop
438
439loop:
440; CHECK: loop:
441; CHECK: %unrelated.cond = icmp ult i32 %x, %length
442; CHECK: [[guard_cond:[^ ]+]] = and i1 %unrelated.cond, [[wide_cond]]
443; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[guard_cond]], i32 9) [ "deopt"() ]
444  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
445  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
446  %within.bounds = icmp ult i32 %i, %length
447  %unrelated.cond = icmp ult i32 %x, %length
448  %guard.cond = and i1 %within.bounds, %unrelated.cond
449  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
450
451  %i.i64 = zext i32 %i to i64
452  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
453  %array.i = load i32, i32* %array.i.ptr, align 4
454  %loop.acc.next = add i32 %loop.acc, %array.i
455
456  %i.next = add nuw i32 %i, 1
457  %continue = icmp ult i32 %i.next, %n
458  br i1 %continue, label %loop, label %exit
459
460exit:
461  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
462  ret i32 %result
463}
464
465; Don't change the guard condition if there were no widened subconditions
466define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
467; CHECK-LABEL: @test_no_widened_conditions
468entry:
469  %tmp5 = icmp eq i32 %n, 0
470  br i1 %tmp5, label %exit, label %loop.preheader
471
472loop.preheader:
473; CHECK: loop.preheader:
474; CHECK-NEXT: br label %loop
475  br label %loop
476
477loop:
478; CHECK: loop:
479; CHECK: %unrelated.cond.1 = icmp eq i32 %x1, %i
480; CHECK-NEXT: %unrelated.cond.2 = icmp eq i32 %x2, %i
481; CHECK-NEXT: %unrelated.cond.3 = icmp eq i32 %x3, %i
482; CHECK-NEXT: %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
483; CHECK-NEXT: %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
484; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
485  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
486  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
487  %unrelated.cond.1 = icmp eq i32 %x1, %i
488  %unrelated.cond.2 = icmp eq i32 %x2, %i
489  %unrelated.cond.3 = icmp eq i32 %x3, %i
490  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
491  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
492
493  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
494
495  %i.i64 = zext i32 %i to i64
496  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
497  %array.i = load i32, i32* %array.i.ptr, align 4
498  %loop.acc.next = add i32 %loop.acc, %array.i
499
500  %i.next = add nuw i32 %i, 1
501  %continue = icmp ult i32 %i.next, %n
502  br i1 %continue, label %loop, label %exit
503
504exit:
505  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
506  ret i32 %result
507}
508
509define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
510; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound
511entry:
512  %tmp5 = icmp sle i32 %n, 0
513  br i1 %tmp5, label %exit, label %loop.preheader
514
515loop.preheader:
516; CHECK: loop.preheader:
517; CHECK-NEXT: br label %loop
518  br label %loop
519
520loop:
521; CHECK: loop:
522; CHECK: %bound = add i32 %i, %x
523; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %bound
524; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
525  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
526  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
527  %bound = add i32 %i, %x
528  %within.bounds = icmp ult i32 %i, %bound
529  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
530
531  %i.i64 = zext i32 %i to i64
532  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
533  %array.i = load i32, i32* %array.i.ptr, align 4
534  %loop.acc.next = add i32 %loop.acc, %array.i
535
536  %i.next = add nsw i32 %i, 1
537  %continue = icmp slt i32 %i.next, %n
538  br i1 %continue, label %loop, label %exit
539
540exit:
541  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
542  ret i32 %result
543}
544
545define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
546; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate
547entry:
548  %tmp5 = icmp sle i32 %n, 0
549  br i1 %tmp5, label %exit, label %loop.preheader
550
551loop.preheader:
552; CHECK: loop.preheader:
553; CHECK-NEXT: br label %loop
554  br label %loop
555
556loop:
557; CHECK: loop:
558; CHECK: %guard.cond = icmp eq i32 %i, %x
559; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
560  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
561  %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
562  %guard.cond = icmp eq i32 %i, %x
563  call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
564
565  %i.i64 = zext i32 %i to i64
566  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
567  %array.i = load i32, i32* %array.i.ptr, align 4
568  %loop.acc.next = add i32 %loop.acc, %array.i
569
570  %i.next = add nsw i32 %i, 1
571  %continue = icmp slt i32 %i.next, %n
572  br i1 %continue, label %loop, label %exit
573
574exit:
575  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
576  ret i32 %result
577}
578
579define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
580; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length
581entry:
582  %tmp5 = icmp eq i32 %n, 0
583  br i1 %tmp5, label %exit, label %loop.preheader
584
585loop.preheader:
586; CHECK: loop.preheader:
587; CHECK: [[length:[^ ]+]] = zext i16 %length.i16 to i32
588; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, [[length]]
589; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, [[length]]
590; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
591; CHECK-NEXT: br label %loop
592  br label %loop
593
594loop:
595; CHECK: loop:
596; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
597  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
598  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
599  %length = zext i16 %length.i16 to i32
600  %within.bounds = icmp ult i32 %i, %length
601  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, 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 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
618; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length
619entry:
620  %tmp5 = icmp eq 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-NEXT: %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
631; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
632; CHECK-NEXT: %length.udiv = udiv i32 %length, %divider
633; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %length.udiv
634; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
635  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
636  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
637  %length.udiv = udiv i32 %length, %divider
638  %within.bounds = icmp ult i32 %i, %length.udiv
639  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
640
641  %i.i64 = zext i32 %i to i64
642  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
643  %array.i = load i32, i32* %array.i.ptr, align 4
644  %loop.acc.next = add i32 %loop.acc, %array.i
645
646  %i.next = add nuw i32 %i, 1
647  %continue = icmp ult i32 %i.next, %n
648  br i1 %continue, label %loop, label %exit
649
650exit:
651  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
652  ret i32 %result
653}
654