blob: a4b4e742a10d0c59c56cd5c2cd28e26afcb0ae87 [file] [log] [blame]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +00001; 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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +000014; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +000017; 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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +000050; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +000053; 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
Artur Pilipenko889dc1e2017-09-22 13:13:57 +000078define 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}
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000257
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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000267; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000273; 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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000315; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000324; 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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000373; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000382; 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
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000425define 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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000433; 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]]
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000436; 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
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000523; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %bound
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000524; 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
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000528 %within.bounds = icmp ult i32 %i, %bound
Artur Pilipenko8fb3d572017-01-25 16:00:44 +0000529 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
Artur Pilipenko0860bfc2017-02-27 15:44:49 +0000577}
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:
Artur Pilipenko889dc1e2017-09-22 13:13:57 +0000587; 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]]
Artur Pilipenko0860bfc2017-02-27 15:44:49 +0000591; 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}