• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -basic-aa -loop-predication < %s 2>&1 | FileCheck %s
3; RUN: opt -S -aa-pipeline=basic-aa -passes='require<aa>,require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
4
5declare void @llvm.experimental.guard(i1, ...)
6
7@UNKNOWN = external global i1
8
9define i32 @neg_length_variant(i32* %array, i32* %length, i32 %n) {
10; CHECK-LABEL: @neg_length_variant(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
13; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
14; CHECK:       loop.preheader:
15; CHECK-NEXT:    br label [[LOOP:%.*]]
16; CHECK:       loop:
17; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
18; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
19; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
20; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
21; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4
22; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]
23; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
24; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
25; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
26; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
27; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
28; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
29; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
30; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
31; CHECK:       exit.loopexit:
32; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
33; CHECK-NEXT:    br label [[EXIT]]
34; CHECK:       exit:
35; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
36; CHECK-NEXT:    ret i32 [[RESULT]]
37;
38entry:
39  %tmp5 = icmp eq i32 %n, 0
40  br i1 %tmp5, label %exit, label %loop.preheader
41
42loop.preheader:
43  br label %loop
44
45loop:
46  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
47  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
48  %unknown = load volatile i1, i1* @UNKNOWN
49  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
50  %len = load i32, i32* %length, align 4
51  %within.bounds = icmp ult i32 %i, %len
52  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
53
54  %i.i64 = zext i32 %i to i64
55  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
56  %array.i = load i32, i32* %array.i.ptr, align 4
57  %loop.acc.next = add i32 %loop.acc, %array.i
58
59  %i.next = add nuw i32 %i, 1
60  %continue = icmp ult i32 %i.next, %n
61  br i1 %continue, label %loop, label %exit
62
63exit:
64  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
65  ret i32 %result
66}
67
68define i32 @invariant_load_guard_limit(i32* %array, i32* %length, i32 %n) {
69; CHECK-LABEL: @invariant_load_guard_limit(
70; CHECK-NEXT:  entry:
71; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
72; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
73; CHECK:       loop.preheader:
74; CHECK-NEXT:    br label [[LOOP:%.*]]
75; CHECK:       loop:
76; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
77; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
78; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
79; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
80; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0
81; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]]
82; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LEN]]
83; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
84; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
85; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
86; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
87; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
88; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
89; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
90; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
91; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
92; CHECK:       exit.loopexit:
93; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
94; CHECK-NEXT:    br label [[EXIT]]
95; CHECK:       exit:
96; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
97; CHECK-NEXT:    ret i32 [[RESULT]]
98;
99entry:
100  %tmp5 = icmp eq i32 %n, 0
101  br i1 %tmp5, label %exit, label %loop.preheader
102
103loop.preheader:
104  br label %loop
105
106loop:
107  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
108  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
109  %unknown = load volatile i1, i1* @UNKNOWN
110  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
111  %len = load i32, i32* %length, align 4, !invariant.load !{}
112  %within.bounds = icmp ult i32 %i, %len
113  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
114
115  %i.i64 = zext i32 %i to i64
116  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
117  %array.i = load i32, i32* %array.i.ptr, align 4
118  %loop.acc.next = add i32 %loop.acc, %array.i
119
120  %i.next = add nuw i32 %i, 1
121  %continue = icmp ult i32 %i.next, %n
122  br i1 %continue, label %loop, label %exit
123
124exit:
125  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
126  ret i32 %result
127}
128
129; Case where we have an invariant load, but it's not loading from a loop
130; invariant location.
131define i32 @neg_varying_invariant_load_op(i32* %array, i32* %lengths, i32 %n) {
132; CHECK-LABEL: @neg_varying_invariant_load_op(
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
135; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
136; CHECK:       loop.preheader:
137; CHECK-NEXT:    br label [[LOOP:%.*]]
138; CHECK:       loop:
139; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
140; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
141; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
142; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
143; CHECK-NEXT:    [[LENGTH_ADDR:%.*]] = getelementptr i32, i32* [[LENGTHS:%.*]], i32 [[I]]
144; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LENGTH_ADDR]], align 4, !invariant.load !0
145; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]
146; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
147; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
148; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
149; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
150; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
151; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
152; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
153; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
154; CHECK:       exit.loopexit:
155; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
156; CHECK-NEXT:    br label [[EXIT]]
157; CHECK:       exit:
158; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
159; CHECK-NEXT:    ret i32 [[RESULT]]
160;
161entry:
162  %tmp5 = icmp eq i32 %n, 0
163  br i1 %tmp5, label %exit, label %loop.preheader
164
165loop.preheader:
166  br label %loop
167
168loop:
169  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
170  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
171  %unknown = load volatile i1, i1* @UNKNOWN
172  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
173
174  %length.addr = getelementptr i32, i32* %lengths, i32 %i
175  %len = load i32, i32* %length.addr, align 4, !invariant.load !{}
176  %within.bounds = icmp ult i32 %i, %len
177  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
178
179  %i.i64 = zext i32 %i to i64
180  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
181  %array.i = load i32, i32* %array.i.ptr, align 4
182  %loop.acc.next = add i32 %loop.acc, %array.i
183
184  %i.next = add nuw i32 %i, 1
185  %continue = icmp ult i32 %i.next, %n
186  br i1 %continue, label %loop, label %exit
187
188exit:
189  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
190  ret i32 %result
191}
192
193; This is a case where moving the load which provides the limit for the latch
194; would be invalid, so we can't preform the tempting transform.  Loading the
195; latch limit may fault since we could always fail the guard.
196define i32 @neg_invariant_load_latch_limit(i32* %array, i32* %length, i32 %n) {
197; CHECK-LABEL: @neg_invariant_load_latch_limit(
198; CHECK-NEXT:  entry:
199; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
200; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
201; CHECK:       loop.preheader:
202; CHECK-NEXT:    br label [[LOOP:%.*]]
203; CHECK:       loop:
204; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
205; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
206; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
207; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
208; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]
209; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
210; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
211; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
212; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
213; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
214; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
215; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0
216; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]
217; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
218; CHECK:       exit.loopexit:
219; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
220; CHECK-NEXT:    br label [[EXIT]]
221; CHECK:       exit:
222; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
223; CHECK-NEXT:    ret i32 [[RESULT]]
224;
225entry:
226  %tmp5 = icmp eq i32 %n, 0
227  br i1 %tmp5, label %exit, label %loop.preheader
228
229loop.preheader:
230  br label %loop
231
232loop:
233  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
234  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
235  %unknown = load volatile i1, i1* @UNKNOWN
236  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
237  %within.bounds = icmp ult i32 %i, %n
238  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
239
240  %i.i64 = zext i32 %i to i64
241  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
242  %array.i = load i32, i32* %array.i.ptr, align 4
243  %loop.acc.next = add i32 %loop.acc, %array.i
244
245  %i.next = add nuw i32 %i, 1
246  %len = load i32, i32* %length, align 4, !invariant.load !{}
247  %continue = icmp ult i32 %i.next, %len
248  br i1 %continue, label %loop, label %exit
249
250exit:
251  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
252  ret i32 %result
253}
254
255define i32 @invariant_load_latch_limit(i32* %array,
256; CHECK-LABEL: @invariant_load_latch_limit(
257; CHECK-NEXT:  entry:
258; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
259; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
260; CHECK:       loop.preheader:
261; CHECK-NEXT:    br label [[LOOP:%.*]]
262; CHECK:       loop:
263; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
264; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
265; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
266; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
267; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]
268; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
269; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
270; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
271; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
272; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
273; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
274; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0
275; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]
276; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
277; CHECK:       exit.loopexit:
278; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
279; CHECK-NEXT:    br label [[EXIT]]
280; CHECK:       exit:
281; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
282; CHECK-NEXT:    ret i32 [[RESULT]]
283;
284  i32* dereferenceable(4) %length,
285  i32 %n) {
286entry:
287  %tmp5 = icmp eq i32 %n, 0
288  br i1 %tmp5, label %exit, label %loop.preheader
289
290loop.preheader:
291  br label %loop
292
293loop:
294  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
295  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
296  %unknown = load volatile i1, i1* @UNKNOWN
297  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
298  %within.bounds = icmp ult i32 %i, %n
299  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
300
301  %i.i64 = zext i32 %i to i64
302  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
303  %array.i = load i32, i32* %array.i.ptr, align 4
304  %loop.acc.next = add i32 %loop.acc, %array.i
305
306  %i.next = add nuw i32 %i, 1
307  %len = load i32, i32* %length, align 4, !invariant.load !{}
308  %continue = icmp ult i32 %i.next, %len
309  br i1 %continue, label %loop, label %exit
310
311exit:
312  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
313  ret i32 %result
314}
315
316
317
318@Length = external constant i32
319
320define i32 @constant_memory(i32* %array, i32 %n) {
321; CHECK-LABEL: @constant_memory(
322; CHECK-NEXT:  entry:
323; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
324; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
325; CHECK:       loop.preheader:
326; CHECK-NEXT:    br label [[LOOP:%.*]]
327; CHECK:       loop:
328; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
329; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
330; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
331; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
332; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* @Length, align 4
333; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]]
334; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LEN]]
335; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
336; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
337; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
338; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
339; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
340; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
341; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
342; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
343; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
344; CHECK:       exit.loopexit:
345; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
346; CHECK-NEXT:    br label [[EXIT]]
347; CHECK:       exit:
348; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
349; CHECK-NEXT:    ret i32 [[RESULT]]
350;
351entry:
352  %tmp5 = icmp eq i32 %n, 0
353  br i1 %tmp5, label %exit, label %loop.preheader
354
355loop.preheader:
356  br label %loop
357
358loop:
359  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
360  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
361  %unknown = load volatile i1, i1* @UNKNOWN
362  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
363  %len = load i32, i32* @Length, align 4
364  %within.bounds = icmp ult i32 %i, %len
365  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
366
367  %i.i64 = zext i32 %i to i64
368  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
369  %array.i = load i32, i32* %array.i.ptr, align 4
370  %loop.acc.next = add i32 %loop.acc, %array.i
371
372  %i.next = add nuw i32 %i, 1
373  %continue = icmp ult i32 %i.next, %n
374  br i1 %continue, label %loop, label %exit
375
376exit:
377  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
378  ret i32 %result
379}
380
381define i32 @constant_length(i32* %array, i32 %n) {
382; CHECK-LABEL: @constant_length(
383; CHECK-NEXT:  entry:
384; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
385; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
386; CHECK:       loop.preheader:
387; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], 20
388; CHECK-NEXT:    [[TMP1:%.*]] = and i1 true, [[TMP0]]
389; CHECK-NEXT:    br label [[LOOP:%.*]]
390; CHECK:       loop:
391; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
392; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
393; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
394; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
395; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
396; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
397; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
398; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
399; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
400; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
401; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
402; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
403; CHECK:       exit.loopexit:
404; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
405; CHECK-NEXT:    br label [[EXIT]]
406; CHECK:       exit:
407; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
408; CHECK-NEXT:    ret i32 [[RESULT]]
409;
410entry:
411  %tmp5 = icmp eq i32 %n, 0
412  br i1 %tmp5, label %exit, label %loop.preheader
413
414loop.preheader:
415  br label %loop
416
417loop:
418  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
419  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
420  %unknown = load volatile i1, i1* @UNKNOWN
421  call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
422  %within.bounds = icmp ult i32 %i, 20
423  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
424
425  %i.i64 = zext i32 %i to i64
426  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
427  %array.i = load i32, i32* %array.i.ptr, align 4
428  %loop.acc.next = add i32 %loop.acc, %array.i
429
430  %i.next = add nuw i32 %i, 1
431  %continue = icmp ult i32 %i.next, %n
432  br i1 %continue, label %loop, label %exit
433
434exit:
435  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
436  ret i32 %result
437}
438
439
440