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