[win/asan] GetInstructionSize: Fix `83 E4 XX` to return 3. (#119644)
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / post-inc-range.ll
blobbbdee0267effb720481faf56530dac348112c266
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
4 target datalayout = "p:64:64:64-n32:64"
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.
10 define 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
36 for.body.lr.ph:
37   br label %for.body
39 for.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
44 continue:
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
50 for.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
55 for.end:
56   br label %exit
58 exit:
59   ret void
62 define 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
88 for.body.lr.ph:
89   br label %for.body
91 for.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
96 continue:
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
102 for.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
107 for.end:
108   br label %exit
110 exit:
111   ret void
114 define 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
137   i32 %limit, i32 %start) {
139 for.body.lr.ph:
140   br label %for.body
142 for.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
148 continue:
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
154 for.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
159 for.end:
160   br label %exit
162 exit:
163   ret void
166 ; Negative version of the test above, we don't know anything about
167 ; array_length_ptr range.
168 define 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
191   i32 %limit, i32 %start) {
193 for.body.lr.ph:
194   br label %for.body
196 for.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
202 continue:
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
208 for.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
213 for.end:
214   br label %exit
216 exit:
217   ret void
220 define 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
253 for.body.lr.ph:
254   br label %for.body
256 for.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
261 continue:
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
266 guarded:
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
271 continue.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
277 for.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
283 for.end:
284   br label %exit
286 exit:
287   ret void
290 declare void @llvm.experimental.guard(i1, ...)
292 define 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
311 for.body.lr.ph:
312   br label %for.body
314 for.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
325 for.end:
326   br label %exit
328 exit:
329   ret void
332 define 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
353 for.body.lr.ph:
354   br label %for.body
356 for.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
364 for.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
370 for.end:
371   br label %exit
373 exit:
374   ret void
377 define 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
398 for.body.lr.ph:
399   br label %for.body
401 for.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
410 for.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
415 for.end:
416   br label %exit
418 exit:
419   ret void
422 define 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
443 for.body.lr.ph:
444   br label %for.body
446 for.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
459 for.end:
460   br label %exit
462 exit:
463   ret void