1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=indvars -scalar-evolution-use-expensive-range-sharpening -S | FileCheck %s
4 target triple = "aarch64--linux-gnu"
6 ; Provide legal integer types.
7 target datalayout = "n8:16:32:64"
10 ; Check the loop exit i32 compare instruction and operand are widened to i64
11 ; instead of truncating IV before its use in the i32 compare instruction.
13 @idx = common global i32 0, align 4
14 @e = common global i32 0, align 4
15 @ptr = common global ptr null, align 8
19 ; CHECK-LABEL: @test1(
21 ; CHECK-NEXT: store i32 -1, ptr @idx, align 4
22 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @e, align 4
23 ; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[TMP0]], 0
24 ; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY_LR_PH:%.*]]
25 ; CHECK: for.body.lr.ph:
26 ; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
27 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @e, align 4
28 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP2]], i32 0)
29 ; CHECK-NEXT: [[TMP3:%.*]] = add nuw i32 [[SMAX]], 1
30 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP3]] to i64
31 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
33 ; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV:%.*]], 1
34 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
35 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_LOOPEXIT_CRIT_EDGE:%.*]]
37 ; CHECK-NEXT: [[INDVARS_IV]] = phi i64 [ [[INDVARS_IV_NEXT]], [[FOR_COND:%.*]] ], [ 0, [[FOR_BODY_LR_PH]] ]
38 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[INDVARS_IV]]
39 ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
40 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP4]], 0
41 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[FOR_COND]]
43 ; CHECK-NEXT: [[I_05_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV]], [[FOR_BODY]] ]
44 ; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[I_05_LCSSA_WIDE]] to i32
45 ; CHECK-NEXT: store i32 [[TMP5]], ptr @idx, align 4
46 ; CHECK-NEXT: br label [[FOR_END:%.*]]
47 ; CHECK: for.cond.for.end.loopexit_crit_edge:
48 ; CHECK-NEXT: br label [[FOR_END_LOOPEXIT]]
49 ; CHECK: for.end.loopexit:
50 ; CHECK-NEXT: br label [[FOR_END]]
52 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr @idx, align 4
53 ; CHECK-NEXT: ret i32 [[TMP6]]
56 store i32 -1, ptr @idx, align 4
57 %0 = load i32, ptr @e, align 4
58 %cmp4 = icmp slt i32 %0, 0
59 br i1 %cmp4, label %for.end.loopexit, label %for.body.lr.ph
62 %1 = load ptr, ptr @ptr, align 8
63 %2 = load i32, ptr @e, align 4
67 %inc = add nsw i32 %i.05, 1
68 %cmp = icmp slt i32 %i.05, %2
69 br i1 %cmp, label %for.body, label %for.cond.for.end.loopexit_crit_edge
72 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.cond ]
73 %idxprom = sext i32 %i.05 to i64
74 %arrayidx = getelementptr inbounds i32, ptr %1, i64 %idxprom
75 %3 = load i32, ptr %arrayidx, align 4
76 %tobool = icmp eq i32 %3, 0
77 br i1 %tobool, label %if.then, label %for.cond
80 %i.05.lcssa = phi i32 [ %i.05, %for.body ]
81 store i32 %i.05.lcssa, ptr @idx, align 4
84 for.cond.for.end.loopexit_crit_edge:
85 br label %for.end.loopexit
91 %4 = load i32, ptr @idx, align 4
96 define void @test2(ptr %a, ptr %b, i8 %limit) {
97 ; CHECK-LABEL: @test2(
99 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[LIMIT:%.*]] to i32
100 ; CHECK-NEXT: br i1 undef, label [[FOR_COND1_PREHEADER_PREHEADER:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]]
101 ; CHECK: for.cond1.preheader.us.preheader:
102 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[CONV]], i32 1)
103 ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
104 ; CHECK: for.cond1.preheader.preheader:
105 ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]
106 ; CHECK: for.cond1.preheader.us:
107 ; CHECK-NEXT: [[INDVARS_IV3:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ], [ [[INDVARS_IV_NEXT4:%.*]], [[FOR_INC13_US:%.*]] ]
108 ; CHECK-NEXT: br i1 true, label [[FOR_BODY4_LR_PH_US:%.*]], label [[FOR_INC13_US]]
109 ; CHECK: for.inc13.us.loopexit:
110 ; CHECK-NEXT: br label [[FOR_INC13_US]]
111 ; CHECK: for.inc13.us:
112 ; CHECK-NEXT: [[INDVARS_IV_NEXT4]] = add nuw nsw i64 [[INDVARS_IV3]], 1
113 ; CHECK-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT4]], 4
114 ; CHECK-NEXT: br i1 [[EXITCOND6]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END_LOOPEXIT1:%.*]]
115 ; CHECK: for.body4.us:
116 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY4_LR_PH_US]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY4_US:%.*]] ]
117 ; CHECK-NEXT: [[ARRAYIDX6_US:%.*]] = getelementptr inbounds [8 x i8], ptr [[A:%.*]], i64 [[INDVARS_IV3]], i64 [[INDVARS_IV]]
118 ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX6_US]], align 1
119 ; CHECK-NEXT: [[IDXPROM7_US:%.*]] = zext i8 [[TMP0]] to i64
120 ; CHECK-NEXT: [[ARRAYIDX8_US:%.*]] = getelementptr inbounds i8, ptr [[B:%.*]], i64 [[IDXPROM7_US]]
121 ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX8_US]], align 1
122 ; CHECK-NEXT: store i8 [[TMP1]], ptr [[ARRAYIDX6_US]], align 1
123 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
124 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT:%.*]]
125 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY4_US]], label [[FOR_INC13_US_LOOPEXIT:%.*]]
126 ; CHECK: for.body4.lr.ph.us:
127 ; CHECK-NEXT: [[WIDE_TRIP_COUNT]] = zext i32 [[SMAX]] to i64
128 ; CHECK-NEXT: br label [[FOR_BODY4_US]]
129 ; CHECK: for.cond1.preheader:
130 ; CHECK-NEXT: br i1 false, label [[FOR_INC13:%.*]], label [[FOR_INC13]]
132 ; CHECK-NEXT: br i1 false, label [[FOR_COND1_PREHEADER]], label [[FOR_END_LOOPEXIT:%.*]]
133 ; CHECK: for.end.loopexit:
134 ; CHECK-NEXT: br label [[FOR_END:%.*]]
135 ; CHECK: for.end.loopexit1:
136 ; CHECK-NEXT: br label [[FOR_END]]
138 ; CHECK-NEXT: ret void
141 %conv = zext i8 %limit to i32
142 br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us
144 for.cond1.preheader.us:
145 %storemerge5.us = phi i32 [ 0, %entry ], [ %inc14.us, %for.inc13.us ]
146 br i1 true, label %for.body4.lr.ph.us, label %for.inc13.us
149 %inc14.us = add nsw i32 %storemerge5.us, 1
150 %cmp.us = icmp slt i32 %inc14.us, 4
151 br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end
154 %storemerge14.us = phi i32 [ 0, %for.body4.lr.ph.us ], [ %inc.us, %for.body4.us ]
155 %idxprom.us = sext i32 %storemerge14.us to i64
156 %arrayidx6.us = getelementptr inbounds [8 x i8], ptr %a, i64 %idxprom5.us, i64 %idxprom.us
157 %0 = load i8, ptr %arrayidx6.us, align 1
158 %idxprom7.us = zext i8 %0 to i64
159 %arrayidx8.us = getelementptr inbounds i8, ptr %b, i64 %idxprom7.us
160 %1 = load i8, ptr %arrayidx8.us, align 1
161 store i8 %1, ptr %arrayidx6.us, align 1
162 %inc.us = add nsw i32 %storemerge14.us, 1
163 %cmp2.us = icmp slt i32 %inc.us, %conv
164 br i1 %cmp2.us, label %for.body4.us, label %for.inc13.us
167 %idxprom5.us = sext i32 %storemerge5.us to i64
168 br label %for.body4.us
171 %storemerge5 = phi i32 [ 0, %entry ], [ %inc14, %for.inc13 ]
172 br i1 false, label %for.inc13, label %for.inc13
175 %inc14 = add nsw i32 %storemerge5, 1
176 %cmp = icmp slt i32 %inc14, 4
177 br i1 %cmp, label %for.cond1.preheader, label %for.end
184 define i32 @test3(ptr %a, i32 %b) {
185 ; CHECK-LABEL: @test3(
187 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B:%.*]], i32 0)
188 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
189 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
191 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
192 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
193 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
194 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
196 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
197 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
198 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP0]]
199 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
200 ; CHECK-NEXT: br label [[FOR_COND]]
202 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
203 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
209 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
210 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
211 %cmp = icmp slt i32 %i.0, %b
212 br i1 %cmp, label %for.body, label %for.end
215 %idxprom = sext i32 %i.0 to i64
216 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
217 %0 = load i32, ptr %arrayidx, align 4
218 %add = add nsw i32 %sum.0, %0
219 %inc = add nsw i32 %i.0, 1
226 declare i32 @fn1(i8 signext)
230 define i32 @test4(i32 %a) {
231 ; CHECK-LABEL: @test4(
233 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
235 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 253, [[ENTRY:%.*]] ]
236 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A:%.*]], [[INDVARS_IV]]
237 ; CHECK-NEXT: [[CONV3:%.*]] = trunc i32 [[OR]] to i8
238 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i8 signext [[CONV3]])
239 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i32 [[INDVARS_IV]], -1
240 ; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[INDVARS_IV_NEXT]] to i8
241 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[TMP0]], -14
242 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
244 ; CHECK-NEXT: ret i32 0
250 %c.07 = phi i8 [ -3, %entry ], [ %dec, %for.body ]
251 %conv6 = zext i8 %c.07 to i32
252 %or = or i32 %a, %conv6
253 %conv3 = trunc i32 %or to i8
254 %call = call i32 @fn1(i8 signext %conv3)
255 %dec = add i8 %c.07, -1
256 %cmp = icmp sgt i8 %dec, -14
257 br i1 %cmp, label %for.body, label %for.end
264 define i32 @test5(ptr %a, i32 %b) {
265 ; CHECK-LABEL: @test5(
267 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64
268 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
270 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
271 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
272 ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]]
273 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
275 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
276 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
277 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
278 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
279 ; CHECK-NEXT: br label [[FOR_COND]]
281 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
282 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
288 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
289 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
290 %cmp = icmp ule i32 %i.0, %b
291 br i1 %cmp, label %for.body, label %for.end
294 %idxprom = zext i32 %i.0 to i64
295 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
296 %0 = load i32, ptr %arrayidx, align 4
297 %add = add nsw i32 %sum.0, %0
298 %inc = add nsw i32 %i.0, 1
305 define i32 @test6(ptr %a, i32 %b) {
306 ; CHECK-LABEL: @test6(
308 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B:%.*]], i32 -1)
309 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SMAX]], 1
310 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64
311 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
313 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
314 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
315 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
316 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
318 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
319 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
320 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
321 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
322 ; CHECK-NEXT: br label [[FOR_COND]]
324 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
325 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
331 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
332 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
333 %cmp = icmp sle i32 %i.0, %b
334 br i1 %cmp, label %for.body, label %for.end
337 %idxprom = zext i32 %i.0 to i64
338 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
339 %0 = load i32, ptr %arrayidx, align 4
340 %add = add nsw i32 %sum.0, %0
341 %inc = add nsw i32 %i.0, 1
348 define i32 @test7(ptr %a, i32 %b) {
349 ; CHECK-LABEL: @test7(
351 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64
352 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 -1)
353 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[SMAX]], 2
354 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
355 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
357 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
358 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
359 ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]]
360 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
362 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
363 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
364 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
365 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
366 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
367 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END]]
369 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
370 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
376 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
377 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
378 %cmp = icmp ule i32 %i.0, %b
379 br i1 %cmp, label %for.body, label %for.end
382 %idxprom = sext i32 %i.0 to i64
383 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
384 %0 = load i32, ptr %arrayidx, align 4
385 %add = add nsw i32 %sum.0, %0
386 %inc = add nsw i32 %i.0, 1
387 %cmp2 = icmp sle i32 %i.0, %b
388 br i1 %cmp2, label %for.cond, label %for.end
394 define i32 @test8(ptr %a, i32 %b, i32 %init) {
395 ; Note: %indvars.iv is the sign extension of %i.0
396 ; CHECK-LABEL: @test8(
398 ; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
399 ; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
400 ; CHECK: for.cond.preheader:
401 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INIT]] to i64
402 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[B:%.*]] to i64
403 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
405 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
406 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
407 ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP1]]
408 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
410 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
411 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
412 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
413 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
414 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 0, [[INDVARS_IV_NEXT]]
415 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
417 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
418 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
420 ; CHECK-NEXT: ret i32 0
423 %e = icmp sgt i32 %init, 0
424 br i1 %e, label %for.cond, label %leave
427 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
428 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
429 %cmp = icmp ule i32 %i.0, %b
430 br i1 %cmp, label %for.body, label %for.end
433 %idxprom = sext i32 %i.0 to i64
434 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
435 %0 = load i32, ptr %arrayidx, align 4
436 %add = add nsw i32 %sum.0, %0
437 %inc = add nsw i32 %i.0, 1
438 %cmp2 = icmp slt i32 0, %inc
439 br i1 %cmp2, label %for.cond, label %for.end
448 define i32 @test9(ptr %a, i32 %b, i32 %init) {
449 ; Note: %indvars.iv is the zero extension of %i.0
450 ; CHECK-LABEL: @test9(
452 ; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
453 ; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
454 ; CHECK: for.cond.preheader:
455 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[INIT]] to i64
456 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INIT]], i32 [[B:%.*]])
457 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
458 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
460 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
461 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
462 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
463 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
465 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
466 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
467 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
468 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
469 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
470 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[TMP2]]
471 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
473 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
474 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
476 ; CHECK-NEXT: ret i32 0
479 %e = icmp sgt i32 %init, 0
480 br i1 %e, label %for.cond, label %leave
483 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
484 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
485 %cmp = icmp slt i32 %i.0, %b
486 br i1 %cmp, label %for.body, label %for.end
489 %idxprom = zext i32 %i.0 to i64
490 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
491 %0 = load i32, ptr %arrayidx, align 4
492 %add = add nsw i32 %sum.0, %0
493 %inc = add nsw i32 %i.0, 1
494 %cmp2 = icmp slt i32 0, %inc
495 br i1 %cmp2, label %for.cond, label %for.end
504 declare void @consume.i64(i64)
505 declare void @consume.i1(i1)
507 define i32 @test10(i32 %v) {
508 ; CHECK-LABEL: @test10(
510 ; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[V:%.*]] to i64
511 ; CHECK-NEXT: br label [[LOOP:%.*]]
513 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
514 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
515 ; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVARS_IV]], -1
516 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], [[SEXT]]
517 ; CHECK-NEXT: call void @consume.i1(i1 [[TMP1]])
518 ; CHECK-NEXT: call void @consume.i64(i64 [[TMP0]])
519 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 11
520 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE:%.*]]
522 ; CHECK-NEXT: ret i32 22
529 %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
530 %i.inc = add i32 %i, 1
532 %cmp = icmp eq i32 %iv, %v
533 call void @consume.i1(i1 %cmp)
534 %be.cond = icmp slt i32 %i.inc, 11
535 %ext = sext i32 %iv to i64
536 call void @consume.i64(i64 %ext)
537 br i1 %be.cond, label %loop, label %leave
543 ; TODO: We don't really need trunc/zext here because when iv.next overflows,
544 ; its value is not used.
545 define i32 @test11(i32 %start, ptr %p, ptr %q) {
546 ; CHECK-LABEL: @test11(
548 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
549 ; CHECK-NEXT: br label [[LOOP:%.*]]
551 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
552 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
553 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
554 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
555 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
557 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
558 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
559 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
560 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
561 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
563 ; CHECK-NEXT: ret i32 0
565 ; CHECK-NEXT: unreachable
571 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
572 %iv.next = add i32 %iv, -1
573 %cond = icmp eq i32 %iv, 0
574 br i1 %cond, label %exit, label %backedge
577 %index = zext i32 %iv.next to i64
578 %store.addr = getelementptr i32, ptr %p, i64 %index
579 store i32 1, ptr %store.addr
580 %load.addr = getelementptr i32, ptr %q, i64 %index
581 %stop = load i32, ptr %q
582 %loop.cond = icmp eq i32 %stop, 0
583 br i1 %loop.cond, label %loop, label %failure
592 define i32 @test12(i32 %start, ptr %p, ptr %q) {
593 ; CHECK-LABEL: @test12(
595 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
596 ; CHECK-NEXT: br label [[LOOP:%.*]]
598 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
599 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
600 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
602 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
603 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
604 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
605 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
606 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
607 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
608 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
610 ; CHECK-NEXT: ret i32 0
612 ; CHECK-NEXT: unreachable
618 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
619 %cond = icmp eq i32 %iv, 0
620 br i1 %cond, label %exit, label %backedge
623 %iv.next = add i32 %iv, -1
624 %index = zext i32 %iv.next to i64
625 %store.addr = getelementptr i32, ptr %p, i64 %index
626 store i32 1, ptr %store.addr
627 %load.addr = getelementptr i32, ptr %q, i64 %index
628 %stop = load i32, ptr %q
629 %loop.cond = icmp eq i32 %stop, 0
630 br i1 %loop.cond, label %loop, label %failure
639 define i32 @test13(i32 %start, ptr %p, ptr %q) {
640 ; CHECK-LABEL: @test13(
642 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
643 ; CHECK-NEXT: br label [[LOOP:%.*]]
645 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
646 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
647 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
649 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
650 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
651 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
652 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
653 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
654 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
655 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
657 ; CHECK-NEXT: ret i32 0
659 ; CHECK-NEXT: unreachable
665 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
666 %cond = icmp eq i32 %iv, 0
667 br i1 %cond, label %exit, label %backedge
670 %foo = add i32 %iv, -1
671 %index = zext i32 %foo to i64
672 %store.addr = getelementptr i32, ptr %p, i64 %index
673 store i32 1, ptr %store.addr
674 %load.addr = getelementptr i32, ptr %q, i64 %index
675 %stop = load i32, ptr %q
676 %loop.cond = icmp eq i32 %stop, 0
677 %iv.next.1 = add i32 %iv, -1
678 br i1 %loop.cond, label %loop, label %failure
687 define i32 @test14(i32 %start, ptr %p, ptr %q) {
688 ; CHECK-LABEL: @test14(
690 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
691 ; CHECK-NEXT: br label [[LOOP:%.*]]
693 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
694 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
695 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
696 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
698 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
699 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
700 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
701 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
702 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
703 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
705 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
706 ; CHECK-NEXT: ret i32 [[TMP2]]
708 ; CHECK-NEXT: unreachable
714 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
715 %cond = icmp eq i32 %iv, 0
716 %foo = add i32 %iv, -1
717 br i1 %cond, label %exit, label %backedge
720 %index = zext i32 %foo to i64
721 %store.addr = getelementptr i32, ptr %p, i64 %index
722 store i32 1, ptr %store.addr
723 %load.addr = getelementptr i32, ptr %q, i64 %index
724 %stop = load i32, ptr %q
725 %loop.cond = icmp eq i32 %stop, 0
726 %iv.next.1 = add i32 %iv, -1
727 br i1 %loop.cond, label %loop, label %failure
736 declare void @test14a-callee(i1 %cond)
738 ; Same as @test14 but with unwind exit.
739 ; Trunc instructions must be added below the landing pad.
740 define i32 @test14a(i32 %start, ptr %p, ptr %q, i1 %c) personality i1 1 {
741 ; CHECK-LABEL: @test14a(
743 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
744 ; CHECK-NEXT: br label [[LOOP:%.*]]
746 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
747 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
748 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
749 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
751 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
752 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
753 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
754 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
755 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
756 ; CHECK-NEXT: invoke void @test14a-callee(i1 [[LOOP_COND]])
757 ; CHECK-NEXT: to label [[LOOP]] unwind label [[EXCEPTION:%.*]]
759 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
760 ; CHECK-NEXT: ret i32 [[TMP2]]
762 ; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
763 ; CHECK-NEXT: [[TMP3:%.*]] = landingpad i1
764 ; CHECK-NEXT: cleanup
765 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32
766 ; CHECK-NEXT: ret i32 [[TMP4]]
772 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
773 %cond = icmp eq i32 %iv, 0
774 %foo = add i32 %iv, -1
775 br i1 %cond, label %exit, label %backedge
778 %index = zext i32 %foo to i64
779 %store.addr = getelementptr i32, ptr %p, i64 %index
780 store i32 1, ptr %store.addr
781 %load.addr = getelementptr i32, ptr %q, i64 %index
782 %stop = load i32, ptr %q
783 %loop.cond = icmp eq i32 %stop, 0
784 %iv.next.1 = add i32 %iv, -1
785 invoke void @test14a-callee(i1 %loop.cond) to label %loop unwind label %exception
796 declare void @use(i32 %arg)
798 define i32 @test15(i32 %start, ptr %p, ptr %q) {
799 ; CHECK-LABEL: @test15(
801 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
802 ; CHECK-NEXT: br label [[LOOP:%.*]]
804 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
805 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
806 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
807 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
809 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
810 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
811 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
812 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
813 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
814 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
816 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
817 ; CHECK-NEXT: call void @use(i32 [[TMP2]])
818 ; CHECK-NEXT: ret i32 [[TMP2]]
820 ; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
821 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32
822 ; CHECK-NEXT: call void @use(i32 [[TMP3]])
823 ; CHECK-NEXT: unreachable
829 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
830 %cond = icmp eq i32 %iv, 0
831 %foo = add i32 %iv, -1
832 br i1 %cond, label %exit, label %backedge
835 %index = zext i32 %foo to i64
836 %store.addr = getelementptr i32, ptr %p, i64 %index
837 store i32 1, ptr %store.addr
838 %load.addr = getelementptr i32, ptr %q, i64 %index
839 %stop = load i32, ptr %q
840 %loop.cond = icmp eq i32 %stop, 0
841 %iv.next.1 = add i32 %iv, -1
842 br i1 %loop.cond, label %loop, label %failure
845 call void @use(i32 %foo)
849 call void @use(i32 %foo)
853 define i32 @test16_unsigned_pos1(i32 %start, ptr %p, ptr %q, i32 %x) {
854 ; CHECK-LABEL: @test16_unsigned_pos1(
856 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
857 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], -1
858 ; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X:%.*]] to i64
859 ; CHECK-NEXT: [[ICMP_USER_WIDE_FIRST_ITER:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]]
860 ; CHECK-NEXT: br label [[LOOP:%.*]]
862 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
863 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
864 ; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], -1
865 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
867 ; CHECK-NEXT: br i1 [[ICMP_USER_WIDE_FIRST_ITER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
869 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP3]]
870 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
871 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
872 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
873 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
874 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
876 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 -1 to i32
877 ; CHECK-NEXT: call void @use(i32 [[TMP4]])
878 ; CHECK-NEXT: ret i32 [[TMP4]]
880 ; CHECK-NEXT: [[FOO_LCSSA2_WIDE:%.*]] = phi i64 [ [[TMP3]], [[BACKEDGE]] ]
881 ; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[FOO_LCSSA2_WIDE]] to i32
882 ; CHECK-NEXT: call void @use(i32 [[TMP5]])
883 ; CHECK-NEXT: unreachable
885 ; CHECK-NEXT: ret i32 0
891 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
892 %cond = icmp eq i32 %iv, 0
893 %foo = add i32 %iv, -1
894 br i1 %cond, label %exit, label %guarded
897 %icmp_user = icmp ult i32 %foo, %x
898 br i1 %icmp_user, label %backedge, label %side_exit
901 %index = zext i32 %foo to i64
902 %store.addr = getelementptr i32, ptr %p, i64 %index
903 store i32 1, ptr %store.addr
904 %load.addr = getelementptr i32, ptr %q, i64 %index
905 %stop = load i32, ptr %q
906 %loop.cond = icmp eq i32 %stop, 0
907 %iv.next.1 = add i32 %iv, -1
908 br i1 %loop.cond, label %loop, label %failure
911 call void @use(i32 %foo)
915 call void @use(i32 %foo)
922 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
923 define i32 @test16_unsigned_pos2(i32 %start, ptr %p, ptr %q, i32 %x) {
924 ; CHECK-LABEL: @test16_unsigned_pos2(
926 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
927 ; CHECK-NEXT: br label [[LOOP:%.*]]
929 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
930 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
931 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
932 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
934 ; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X:%.*]] to i64
935 ; CHECK-NEXT: [[ICMP_USER_WIDE:%.*]] = icmp ne i64 [[TMP1]], [[TMP2]]
936 ; CHECK-NEXT: br i1 [[ICMP_USER_WIDE]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
938 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
939 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
940 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
941 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
942 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
943 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
945 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 -1 to i32
946 ; CHECK-NEXT: call void @use(i32 [[TMP3]])
947 ; CHECK-NEXT: ret i32 [[TMP3]]
949 ; CHECK-NEXT: [[FOO_LCSSA2_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
950 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[FOO_LCSSA2_WIDE]] to i32
951 ; CHECK-NEXT: call void @use(i32 [[TMP4]])
952 ; CHECK-NEXT: unreachable
954 ; CHECK-NEXT: ret i32 0
960 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
961 %cond = icmp eq i32 %iv, 0
962 %foo = add i32 %iv, -1
963 br i1 %cond, label %exit, label %guarded
966 %icmp_user = icmp ne i32 %foo, %x
967 br i1 %icmp_user, label %backedge, label %side_exit
970 %index = zext i32 %foo to i64
971 %store.addr = getelementptr i32, ptr %p, i64 %index
972 store i32 1, ptr %store.addr
973 %load.addr = getelementptr i32, ptr %q, i64 %index
974 %stop = load i32, ptr %q
975 %loop.cond = icmp eq i32 %stop, 0
976 %iv.next.1 = add i32 %iv, -1
977 br i1 %loop.cond, label %loop, label %failure
980 call void @use(i32 %foo)
984 call void @use(i32 %foo)
991 ; icmp slt user in guarded block prevents widening.
992 define i32 @test16_unsigned_neg(i32 %start, ptr %p, ptr %q, i32 %x) {
993 ; CHECK-LABEL: @test16_unsigned_neg(
995 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
996 ; CHECK-NEXT: br label [[LOOP:%.*]]
998 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
999 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
1000 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
1001 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[TMP1]], -1
1002 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1004 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]]
1005 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1007 ; CHECK-NEXT: [[INDEX:%.*]] = zext i32 [[FOO]] to i64
1008 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1009 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1010 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1011 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1012 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1013 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
1014 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1016 ; CHECK-NEXT: call void @use(i32 -1)
1017 ; CHECK-NEXT: ret i32 -1
1019 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1020 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1021 ; CHECK-NEXT: unreachable
1023 ; CHECK-NEXT: ret i32 0
1029 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1030 %cond = icmp eq i32 %iv, 0
1031 %foo = add i32 %iv, -1
1032 br i1 %cond, label %exit, label %guarded
1035 %icmp_user = icmp slt i32 %foo, %x
1036 br i1 %icmp_user, label %backedge, label %side_exit
1039 %index = zext i32 %foo to i64
1040 %store.addr = getelementptr i32, ptr %p, i64 %index
1041 store i32 1, ptr %store.addr
1042 %load.addr = getelementptr i32, ptr %q, i64 %index
1043 %stop = load i32, ptr %q
1044 %loop.cond = icmp eq i32 %stop, 0
1045 %iv.next.1 = add i32 %iv, -1
1046 br i1 %loop.cond, label %loop, label %failure
1049 call void @use(i32 %foo)
1053 call void @use(i32 %foo)
1060 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
1061 define i32 @test16_signed_pos1(i32 %start, ptr %p, ptr %q, i32 %x) {
1062 ; CHECK-LABEL: @test16_signed_pos1(
1063 ; CHECK-NEXT: entry:
1064 ; CHECK-NEXT: br label [[LOOP:%.*]]
1066 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1067 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1068 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1069 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1071 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]]
1072 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1074 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1075 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1076 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1077 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1078 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1079 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1080 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1081 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1083 ; CHECK-NEXT: call void @use(i32 -1)
1084 ; CHECK-NEXT: ret i32 -1
1086 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1087 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1088 ; CHECK-NEXT: unreachable
1090 ; CHECK-NEXT: ret i32 0
1096 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1097 %cond = icmp eq i32 %iv, 0
1098 %foo = add i32 %iv, -1
1099 br i1 %cond, label %exit, label %guarded
1102 %icmp_user = icmp slt i32 %foo, %x
1103 br i1 %icmp_user, label %backedge, label %side_exit
1106 %index = sext i32 %foo to i64
1107 %store.addr = getelementptr i32, ptr %p, i64 %index
1108 store i32 1, ptr %store.addr
1109 %load.addr = getelementptr i32, ptr %q, i64 %index
1110 %stop = load i32, ptr %q
1111 %loop.cond = icmp eq i32 %stop, 0
1112 %iv.next.1 = add i32 %iv, -1
1113 br i1 %loop.cond, label %loop, label %failure
1116 call void @use(i32 %foo)
1120 call void @use(i32 %foo)
1127 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
1128 define i32 @test16_signed_pos2(i32 %start, ptr %p, ptr %q, i32 %x) {
1129 ; CHECK-LABEL: @test16_signed_pos2(
1130 ; CHECK-NEXT: entry:
1131 ; CHECK-NEXT: br label [[LOOP:%.*]]
1133 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1134 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1135 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1136 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1138 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp ne i32 [[FOO]], [[X:%.*]]
1139 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1141 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1142 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1143 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1144 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1145 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1146 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1147 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1148 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1150 ; CHECK-NEXT: call void @use(i32 -1)
1151 ; CHECK-NEXT: ret i32 -1
1153 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1154 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1155 ; CHECK-NEXT: unreachable
1157 ; CHECK-NEXT: ret i32 0
1163 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1164 %cond = icmp eq i32 %iv, 0
1165 %foo = add i32 %iv, -1
1166 br i1 %cond, label %exit, label %guarded
1169 %icmp_user = icmp ne i32 %foo, %x
1170 br i1 %icmp_user, label %backedge, label %side_exit
1173 %index = sext i32 %foo to i64
1174 %store.addr = getelementptr i32, ptr %p, i64 %index
1175 store i32 1, ptr %store.addr
1176 %load.addr = getelementptr i32, ptr %q, i64 %index
1177 %stop = load i32, ptr %q
1178 %loop.cond = icmp eq i32 %stop, 0
1179 %iv.next.1 = add i32 %iv, -1
1180 br i1 %loop.cond, label %loop, label %failure
1183 call void @use(i32 %foo)
1187 call void @use(i32 %foo)
1194 ; icmp ult user in guarded block prevents widening.
1195 define i32 @test16_signed_neg(i32 %start, ptr %p, ptr %q, i32 %x) {
1196 ; CHECK-LABEL: @test16_signed_neg(
1197 ; CHECK-NEXT: entry:
1198 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
1199 ; CHECK-NEXT: [[ICMP_USER_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[X:%.*]]
1200 ; CHECK-NEXT: br label [[LOOP:%.*]]
1202 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1203 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1204 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1205 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1207 ; CHECK-NEXT: br i1 [[ICMP_USER_FIRST_ITER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1209 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1210 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1211 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1212 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1213 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1214 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1215 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1216 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1218 ; CHECK-NEXT: call void @use(i32 -1)
1219 ; CHECK-NEXT: ret i32 -1
1221 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1222 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1223 ; CHECK-NEXT: unreachable
1225 ; CHECK-NEXT: ret i32 0
1231 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1232 %cond = icmp eq i32 %iv, 0
1233 %foo = add i32 %iv, -1
1234 br i1 %cond, label %exit, label %guarded
1237 %icmp_user = icmp ult i32 %foo, %x
1238 br i1 %icmp_user, label %backedge, label %side_exit
1241 %index = sext i32 %foo to i64
1242 %store.addr = getelementptr i32, ptr %p, i64 %index
1243 store i32 1, ptr %store.addr
1244 %load.addr = getelementptr i32, ptr %q, i64 %index
1245 %stop = load i32, ptr %q
1246 %loop.cond = icmp eq i32 %stop, 0
1247 %iv.next.1 = add i32 %iv, -1
1248 br i1 %loop.cond, label %loop, label %failure
1251 call void @use(i32 %foo)
1255 call void @use(i32 %foo)
1262 define i32 @test17(ptr %p, i32 %len) {
1263 ; CHECK-LABEL: @test17(
1264 ; CHECK-NEXT: entry:
1265 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LEN:%.*]] to i64
1266 ; CHECK-NEXT: br label [[LOOP:%.*]]
1268 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
1269 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
1270 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
1271 ; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
1272 ; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
1274 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[TMP1]]
1275 ; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
1276 ; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], 0
1277 ; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
1279 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
1280 ; CHECK-NEXT: ret i32 [[TMP2]]
1282 ; CHECK-NEXT: unreachable
1288 %iv = phi i32 [ %iv.next, %backedge ], [ %len, %entry ]
1289 %iv.next = add i32 %iv, -1
1290 %cond_1 = icmp eq i32 %iv, 0
1291 br i1 %cond_1, label %exit, label %backedge
1294 %iv.next.wide = zext i32 %iv.next to i64
1295 %addr = getelementptr inbounds i32, ptr %p, i64 %iv.next.wide
1296 %loaded = load atomic i32, ptr %addr unordered, align 4
1297 %cond_2 = icmp eq i32 %loaded, 0
1298 br i1 %cond_2, label %failure, label %loop
1307 declare void @foo(i64 %v)
1308 declare void @bar(i32 %v)
1310 define void @test18() {
1311 ; CHECK-LABEL: @test18(
1312 ; CHECK-NEXT: entry:
1313 ; CHECK-NEXT: br label [[LOOP:%.*]]
1315 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1316 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1317 ; CHECK-NEXT: [[INDVARS2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1318 ; CHECK-NEXT: call void @bar(i32 [[INDVARS2]])
1319 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1320 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1321 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1323 ; CHECK-NEXT: ret void
1328 loop: ; preds = %loop, %entry
1329 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1330 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ]
1331 %val1.inc = add i32 %val1, 1
1332 %iv.next = add i32 %iv, 1
1333 call void @bar(i32 %val1.inc)
1334 %iv.wide = zext i32 %iv to i64
1335 call void @foo(i64 %iv.wide)
1336 %loop.cond = icmp eq i32 %iv, 1000
1337 br i1 %loop.cond, label %exit, label %loop
1339 exit: ; preds = %loop
1343 define void @test19() {
1344 ; CHECK-LABEL: @test19(
1345 ; CHECK-NEXT: entry:
1346 ; CHECK-NEXT: br label [[LOOP:%.*]]
1348 ; CHECK-NEXT: [[VAL1:%.*]] = phi i64 [ [[VAL1_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1349 ; CHECK-NEXT: [[VAL1_INC]] = add nuw nsw i64 [[VAL1]], 1
1350 ; CHECK-NEXT: call void @foo(i64 [[VAL1_INC]])
1351 ; CHECK-NEXT: call void @foo(i64 [[VAL1]])
1352 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[VAL1]], 1000
1353 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1355 ; CHECK-NEXT: ret void
1360 loop: ; preds = %loop, %entry
1361 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1362 %val1 = phi i64 [ %val1.inc, %loop ], [ 0, %entry ]
1363 %val1.inc = add i64 %val1, 1
1364 %iv.next = add i32 %iv, 1
1365 call void @foo(i64 %val1.inc)
1366 %iv.wide = zext i32 %iv to i64
1367 call void @foo(i64 %iv.wide)
1368 %loop.cond = icmp eq i32 %iv, 1000
1369 br i1 %loop.cond, label %exit, label %loop
1371 exit: ; preds = %loop
1375 define void @test20() {
1376 ; CHECK-LABEL: @test20(
1377 ; CHECK-NEXT: entry:
1378 ; CHECK-NEXT: br label [[LOOP:%.*]]
1380 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1381 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1382 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1383 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1384 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1385 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1387 ; CHECK-NEXT: ret void
1392 loop: ; preds = %loop, %entry
1393 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1394 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ]
1395 %val1.inc = add i32 %val1, 1
1396 %iv.next = add i32 %iv, 1
1397 %val1.wide = zext i32 %val1 to i64
1398 call void @foo(i64 %val1.wide)
1399 %iv.wide = zext i32 %iv to i64
1400 call void @foo(i64 %iv.wide)
1401 %loop.cond = icmp eq i32 %iv, 1000
1402 br i1 %loop.cond, label %exit, label %loop
1404 exit: ; preds = %loop
1408 define void @test21(ptr %ptr) {
1409 ; CHECK-LABEL: @test21(
1410 ; CHECK-NEXT: entry:
1411 ; CHECK-NEXT: store i32 0, ptr [[PTR:%.*]], align 4
1412 ; CHECK-NEXT: br label [[LOOP:%.*]]
1414 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1415 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1416 ; CHECK-NEXT: [[INDVARS:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1417 ; CHECK-NEXT: store i32 [[INDVARS]], ptr [[PTR]], align 4
1418 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1419 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1420 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1422 ; CHECK-NEXT: ret void
1425 store i32 0, ptr %ptr, align 4
1428 loop: ; preds = %loop, %entry
1429 %val = phi i32 [ %val.inc, %loop ], [ 0, %entry ]
1430 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1431 %val.inc = add i32 %val, 1
1432 store i32 %val.inc, ptr %ptr, align 4
1433 %iv.wide = zext i32 %iv to i64
1434 call void @foo(i64 %iv.wide)
1435 %iv.next = add i32 %iv, 1
1436 %loop.cond = icmp eq i32 %iv, 1000
1437 br i1 %loop.cond, label %exit, label %loop
1439 exit: ; preds = %loop
1443 ; Don't perform replacement here; SCEV won't recognize the new PHI as an
1444 ; induction variable.
1445 define void @test22(ptr %ptr) {
1446 ; CHECK-LABEL: @test22(
1447 ; CHECK-NEXT: entry:
1448 ; CHECK-NEXT: store i16 0, ptr [[PTR:%.*]], align 4
1449 ; CHECK-NEXT: br label [[LOOP:%.*]]
1451 ; CHECK-NEXT: [[VAL:%.*]] = phi i16 [ [[VAL_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1452 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ]
1453 ; CHECK-NEXT: [[VAL_INC]] = add i16 [[VAL]], 1
1454 ; CHECK-NEXT: store i16 [[VAL_INC]], ptr [[PTR]], align 4
1455 ; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
1456 ; CHECK-NEXT: call void @foo(i64 [[IV_WIDE]])
1457 ; CHECK-NEXT: [[IV_NEXT]] = zext i16 [[VAL_INC]] to i32
1458 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[IV]], 1000
1459 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1461 ; CHECK-NEXT: ret void
1464 store i16 0, ptr %ptr, align 4
1467 loop: ; preds = %loop, %entry
1468 %val = phi i16 [ %val.inc, %loop ], [ 0, %entry ]
1469 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1470 %val.inc = add i16 %val, 1
1471 store i16 %val.inc, ptr %ptr, align 4
1472 %iv.wide = zext i32 %iv to i64
1473 call void @foo(i64 %iv.wide)
1474 %iv.next = zext i16 %val.inc to i32
1475 %loop.cond = icmp eq i32 %iv, 1000
1476 br i1 %loop.cond, label %exit, label %loop
1478 exit: ; preds = %loop