xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll (revision 4b22a923c4bfd0aa1d483149f84b6787263c2d76)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=indvars -indvars-post-increment-ranges -S | FileCheck %s
3
4target datalayout = "p:64:64:64-n32:64"
5
6; When the IV in this loop is widened we want to widen this use as well:
7; icmp slt i32 %i.inc, %limit
8; In order to do this indvars need to prove that the narrow IV def (%i.inc)
9; is not-negative from the range check inside of the loop.
10define void @test(ptr %base, i32 %limit, i32 %start) {
11; CHECK-LABEL: @test(
12; CHECK-NEXT:  for.body.lr.ph:
13; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START:%.*]], i32 64)
14; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 [[UMAX]], [[START]]
15; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[START]], 1
16; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[LIMIT:%.*]], i32 [[TMP1]])
17; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[SMAX]], -1
18; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], [[START]]
19; CHECK-NEXT:    [[TMP4:%.*]] = freeze i32 [[TMP3]]
20; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP4]], i32 [[TMP0]])
21; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP0]], [[UMIN]]
22; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP3]], [[UMIN]]
23; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
24; CHECK:       for.body:
25; CHECK-NEXT:    br i1 [[TMP5]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]]
26; CHECK:       continue:
27; CHECK-NEXT:    br label [[FOR_INC:%.*]]
28; CHECK:       for.inc:
29; CHECK-NEXT:    br i1 [[TMP6]], label [[FOR_BODY]], label [[FOR_END]]
30; CHECK:       for.end:
31; CHECK-NEXT:    br label [[EXIT:%.*]]
32; CHECK:       exit:
33; CHECK-NEXT:    ret void
34;
35
36for.body.lr.ph:
37  br label %for.body
38
39for.body:
40  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
41  %within_limits = icmp ult i32 %i, 64
42  br i1 %within_limits, label %continue, label %for.end
43
44continue:
45  %i.i64 = zext i32 %i to i64
46  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
47  %val = load i32, ptr %arrayidx, align 4
48  br label %for.inc
49
50for.inc:
51  %i.inc = add nsw nuw i32 %i, 1
52  %cmp = icmp slt i32 %i.inc, %limit
53  br i1 %cmp, label %for.body, label %for.end
54
55for.end:
56  br label %exit
57
58exit:
59  ret void
60}
61
62define void @test_false_edge(ptr %base, i32 %limit, i32 %start) {
63; CHECK-LABEL: @test_false_edge(
64; CHECK-NEXT:  for.body.lr.ph:
65; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START:%.*]], i32 65)
66; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 [[UMAX]], [[START]]
67; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[START]], 1
68; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[LIMIT:%.*]], i32 [[TMP1]])
69; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[SMAX]], -1
70; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], [[START]]
71; CHECK-NEXT:    [[TMP4:%.*]] = freeze i32 [[TMP3]]
72; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP4]], i32 [[TMP0]])
73; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[UMIN]]
74; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP3]], [[UMIN]]
75; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
76; CHECK:       for.body:
77; CHECK-NEXT:    br i1 [[TMP5]], label [[FOR_END:%.*]], label [[CONTINUE:%.*]]
78; CHECK:       continue:
79; CHECK-NEXT:    br label [[FOR_INC:%.*]]
80; CHECK:       for.inc:
81; CHECK-NEXT:    br i1 [[TMP6]], label [[FOR_BODY]], label [[FOR_END]]
82; CHECK:       for.end:
83; CHECK-NEXT:    br label [[EXIT:%.*]]
84; CHECK:       exit:
85; CHECK-NEXT:    ret void
86;
87
88for.body.lr.ph:
89  br label %for.body
90
91for.body:
92  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
93  %out_of_bounds = icmp ugt i32 %i, 64
94  br i1 %out_of_bounds, label %for.end, label %continue
95
96continue:
97  %i.i64 = zext i32 %i to i64
98  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
99  %val = load i32, ptr %arrayidx, align 4
100  br label %for.inc
101
102for.inc:
103  %i.inc = add nsw nuw i32 %i, 1
104  %cmp = icmp slt i32 %i.inc, %limit
105  br i1 %cmp, label %for.body, label %for.end
106
107for.end:
108  br label %exit
109
110exit:
111  ret void
112}
113
114define void @test_range_metadata(ptr %array_length_ptr, ptr %base,
115; CHECK-LABEL: @test_range_metadata(
116; CHECK-NEXT:  for.body.lr.ph:
117; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
118; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
119; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
120; CHECK:       for.body:
121; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
122; CHECK-NEXT:    [[ARRAY_LENGTH:%.*]] = load i32, ptr [[ARRAY_LENGTH_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]]
123; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[ARRAY_LENGTH]] to i64
124; CHECK-NEXT:    [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP2]]
125; CHECK-NEXT:    br i1 [[WITHIN_LIMITS]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]]
126; CHECK:       continue:
127; CHECK-NEXT:    br label [[FOR_INC]]
128; CHECK:       for.inc:
129; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
130; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]]
131; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
132; CHECK:       for.end:
133; CHECK-NEXT:    br label [[EXIT:%.*]]
134; CHECK:       exit:
135; CHECK-NEXT:    ret void
136;
137  i32 %limit, i32 %start) {
138
139for.body.lr.ph:
140  br label %for.body
141
142for.body:
143  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
144  %array_length = load i32, ptr %array_length_ptr, !range !{i32 0, i32 64 }
145  %within_limits = icmp ult i32 %i, %array_length
146  br i1 %within_limits, label %continue, label %for.end
147
148continue:
149  %i.i64 = zext i32 %i to i64
150  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
151  %val = load i32, ptr %arrayidx, align 4
152  br label %for.inc
153
154for.inc:
155  %i.inc = add nsw nuw i32 %i, 1
156  %cmp = icmp slt i32 %i.inc, %limit
157  br i1 %cmp, label %for.body, label %for.end
158
159for.end:
160  br label %exit
161
162exit:
163  ret void
164}
165
166; Negative version of the test above, we don't know anything about
167; array_length_ptr range.
168define void @test_neg(ptr %array_length_ptr, ptr %base,
169; CHECK-LABEL: @test_neg(
170; CHECK-NEXT:  for.body.lr.ph:
171; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
172; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
173; CHECK:       for.body:
174; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
175; CHECK-NEXT:    [[ARRAY_LENGTH:%.*]] = load i32, ptr [[ARRAY_LENGTH_PTR:%.*]], align 4
176; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[ARRAY_LENGTH]] to i64
177; CHECK-NEXT:    [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP1]]
178; CHECK-NEXT:    br i1 [[WITHIN_LIMITS]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]]
179; CHECK:       continue:
180; CHECK-NEXT:    br label [[FOR_INC]]
181; CHECK:       for.inc:
182; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
183; CHECK-NEXT:    [[TMP2:%.*]] = trunc nuw i64 [[INDVARS_IV_NEXT]] to i32
184; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP2]], [[LIMIT:%.*]]
185; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
186; CHECK:       for.end:
187; CHECK-NEXT:    br label [[EXIT:%.*]]
188; CHECK:       exit:
189; CHECK-NEXT:    ret void
190;
191  i32 %limit, i32 %start) {
192
193for.body.lr.ph:
194  br label %for.body
195
196for.body:
197  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
198  %array_length = load i32, ptr %array_length_ptr
199  %within_limits = icmp ult i32 %i, %array_length
200  br i1 %within_limits, label %continue, label %for.end
201
202continue:
203  %i.i64 = zext i32 %i to i64
204  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
205  %val = load i32, ptr %arrayidx, align 4
206  br label %for.inc
207
208for.inc:
209  %i.inc = add nsw nuw i32 %i, 1
210  %cmp = icmp slt i32 %i.inc, %limit
211  br i1 %cmp, label %for.body, label %for.end
212
213for.end:
214  br label %exit
215
216exit:
217  ret void
218}
219
220define void @test_transitive_use(ptr %base, i32 %limit, i32 %start) {
221; CHECK-LABEL: @test_transitive_use(
222; CHECK-NEXT:  for.body.lr.ph:
223; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
224; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
225; CHECK-NEXT:    [[TMP2:%.*]] = sext i32 [[LIMIT]] to i64
226; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START]], i32 64)
227; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[UMAX]] to i64
228; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
229; CHECK:       for.body:
230; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
231; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
232; CHECK-NEXT:    br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]]
233; CHECK:       continue:
234; CHECK-NEXT:    [[TMP3:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 3
235; CHECK-NEXT:    [[MUL_WITHIN:%.*]] = icmp ult i64 [[TMP3]], 64
236; CHECK-NEXT:    br i1 [[MUL_WITHIN]], label [[GUARDED:%.*]], label [[CONTINUE_2:%.*]]
237; CHECK:       guarded:
238; CHECK-NEXT:    [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1
239; CHECK-NEXT:    [[RESULT:%.*]] = icmp slt i64 [[TMP4]], [[TMP1]]
240; CHECK-NEXT:    br i1 [[RESULT]], label [[CONTINUE_2]], label [[FOR_END]]
241; CHECK:       continue.2:
242; CHECK-NEXT:    br label [[FOR_INC]]
243; CHECK:       for.inc:
244; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
245; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP2]]
246; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
247; CHECK:       for.end:
248; CHECK-NEXT:    br label [[EXIT:%.*]]
249; CHECK:       exit:
250; CHECK-NEXT:    ret void
251;
252
253for.body.lr.ph:
254  br label %for.body
255
256for.body:
257  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
258  %within_limits = icmp ult i32 %i, 64
259  br i1 %within_limits, label %continue, label %for.end
260
261continue:
262  %i.mul.3 = mul nsw nuw i32 %i, 3
263  %mul_within = icmp ult i32 %i.mul.3, 64
264  br i1 %mul_within, label %guarded, label %continue.2
265
266guarded:
267  %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1
268  %result = icmp slt i32 %i.mul.3.inc, %limit
269  br i1 %result, label %continue.2, label %for.end
270
271continue.2:
272  %i.i64 = zext i32 %i to i64
273  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
274  %val = load i32, ptr %arrayidx, align 4
275  br label %for.inc
276
277for.inc:
278  %i.inc = add nsw nuw i32 %i, 1
279  %cmp = icmp slt i32 %i.inc, %limit
280  br i1 %cmp, label %for.body, label %for.end
281
282
283for.end:
284  br label %exit
285
286exit:
287  ret void
288}
289
290declare void @llvm.experimental.guard(i1, ...)
291
292define void @test_guard_one_bb(ptr %base, i32 %limit, i32 %start) {
293; CHECK-LABEL: @test_guard_one_bb(
294; CHECK-NEXT:  for.body.lr.ph:
295; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
296; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
297; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
298; CHECK:       for.body:
299; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
300; CHECK-NEXT:    [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64
301; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ]
302; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
303; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]]
304; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
305; CHECK:       for.end:
306; CHECK-NEXT:    br label [[EXIT:%.*]]
307; CHECK:       exit:
308; CHECK-NEXT:    ret void
309;
310
311for.body.lr.ph:
312  br label %for.body
313
314for.body:
315  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
316  %within_limits = icmp ult i32 %i, 64
317  %i.i64 = zext i32 %i to i64
318  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
319  %val = load i32, ptr %arrayidx, align 4
320  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
321  %i.inc = add nsw nuw i32 %i, 1
322  %cmp = icmp slt i32 %i.inc, %limit
323  br i1 %cmp, label %for.body, label %for.end
324
325for.end:
326  br label %exit
327
328exit:
329  ret void
330}
331
332define void @test_guard_in_the_same_bb(ptr %base, i32 %limit, i32 %start) {
333; CHECK-LABEL: @test_guard_in_the_same_bb(
334; CHECK-NEXT:  for.body.lr.ph:
335; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
336; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
337; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
338; CHECK:       for.body:
339; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
340; CHECK-NEXT:    [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64
341; CHECK-NEXT:    br label [[FOR_INC]]
342; CHECK:       for.inc:
343; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ]
344; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
345; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]]
346; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
347; CHECK:       for.end:
348; CHECK-NEXT:    br label [[EXIT:%.*]]
349; CHECK:       exit:
350; CHECK-NEXT:    ret void
351;
352
353for.body.lr.ph:
354  br label %for.body
355
356for.body:
357  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
358  %within_limits = icmp ult i32 %i, 64
359  %i.i64 = zext i32 %i to i64
360  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
361  %val = load i32, ptr %arrayidx, align 4
362  br label %for.inc
363
364for.inc:
365  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
366  %i.inc = add nsw nuw i32 %i, 1
367  %cmp = icmp slt i32 %i.inc, %limit
368  br i1 %cmp, label %for.body, label %for.end
369
370for.end:
371  br label %exit
372
373exit:
374  ret void
375}
376
377define void @test_guard_in_idom(ptr %base, i32 %limit, i32 %start) {
378; CHECK-LABEL: @test_guard_in_idom(
379; CHECK-NEXT:  for.body.lr.ph:
380; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
381; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
382; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
383; CHECK:       for.body:
384; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
385; CHECK-NEXT:    [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64
386; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ]
387; CHECK-NEXT:    br label [[FOR_INC]]
388; CHECK:       for.inc:
389; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
390; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]]
391; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
392; CHECK:       for.end:
393; CHECK-NEXT:    br label [[EXIT:%.*]]
394; CHECK:       exit:
395; CHECK-NEXT:    ret void
396;
397
398for.body.lr.ph:
399  br label %for.body
400
401for.body:
402  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
403  %within_limits = icmp ult i32 %i, 64
404  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
405  %i.i64 = zext i32 %i to i64
406  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
407  %val = load i32, ptr %arrayidx, align 4
408  br label %for.inc
409
410for.inc:
411  %i.inc = add nsw nuw i32 %i, 1
412  %cmp = icmp slt i32 %i.inc, %limit
413  br i1 %cmp, label %for.body, label %for.end
414
415for.end:
416  br label %exit
417
418exit:
419  ret void
420}
421
422define void @test_guard_merge_ranges(ptr %base, i32 %limit, i32 %start) {
423; CHECK-LABEL: @test_guard_merge_ranges(
424; CHECK-NEXT:  for.body.lr.ph:
425; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
426; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64
427; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
428; CHECK:       for.body:
429; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ]
430; CHECK-NEXT:    [[WITHIN_LIMITS_1:%.*]] = icmp ult i64 [[INDVARS_IV]], 64
431; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS_1]]) [ "deopt"() ]
432; CHECK-NEXT:    [[WITHIN_LIMITS_2:%.*]] = icmp ult i64 [[INDVARS_IV]], 2147483647
433; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS_2]]) [ "deopt"() ]
434; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
435; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]]
436; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
437; CHECK:       for.end:
438; CHECK-NEXT:    br label [[EXIT:%.*]]
439; CHECK:       exit:
440; CHECK-NEXT:    ret void
441;
442
443for.body.lr.ph:
444  br label %for.body
445
446for.body:
447  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
448  %within_limits.1 = icmp ult i32 %i, 64
449  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ]
450  %within_limits.2 = icmp ult i32 %i, 2147483647
451  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ]
452  %i.i64 = zext i32 %i to i64
453  %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64
454  %val = load i32, ptr %arrayidx, align 4
455  %i.inc = add nsw nuw i32 %i, 1
456  %cmp = icmp slt i32 %i.inc, %limit
457  br i1 %cmp, label %for.body, label %for.end
458
459for.end:
460  br label %exit
461
462exit:
463  ret void
464}
465