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 nuw nsw 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, i1 %arg) {
97 ; CHECK-LABEL: @test2(
99 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[LIMIT:%.*]] to i32
100 ; CHECK-NEXT: br i1 %arg, 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 %arg, 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 nuw 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: [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1
269 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
271 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
272 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
273 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[TMP1]]
274 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
276 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
277 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
278 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
279 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
280 ; CHECK-NEXT: br label [[FOR_COND]]
282 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
283 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
289 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
290 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
291 %cmp = icmp ule i32 %i.0, %b
292 br i1 %cmp, label %for.body, label %for.end
295 %idxprom = zext i32 %i.0 to i64
296 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
297 %0 = load i32, ptr %arrayidx, align 4
298 %add = add nsw i32 %sum.0, %0
299 %inc = add nsw i32 %i.0, 1
306 define i32 @test6(ptr %a, i32 %b) {
307 ; CHECK-LABEL: @test6(
309 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B:%.*]], i32 -1)
310 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SMAX]], 1
311 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64
312 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
314 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
315 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
316 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
317 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
319 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
320 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
321 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
322 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
323 ; CHECK-NEXT: br label [[FOR_COND]]
325 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
326 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
332 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
333 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
334 %cmp = icmp sle i32 %i.0, %b
335 br i1 %cmp, label %for.body, label %for.end
338 %idxprom = zext i32 %i.0 to i64
339 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
340 %0 = load i32, ptr %arrayidx, align 4
341 %add = add nsw i32 %sum.0, %0
342 %inc = add nsw i32 %i.0, 1
349 define i32 @test7(ptr %a, i32 %b) {
350 ; CHECK-LABEL: @test7(
352 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64
353 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1
354 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 -1)
355 ; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[SMAX]], 2
356 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP2]] to i64
357 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
359 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
360 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
361 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[TMP1]]
362 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
364 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
365 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
366 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP3]]
367 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
368 ; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
369 ; CHECK-NEXT: br i1 [[EXITCOND2]], label [[FOR_COND]], label [[FOR_END]]
371 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
372 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
378 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
379 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
380 %cmp = icmp ule i32 %i.0, %b
381 br i1 %cmp, label %for.body, label %for.end
384 %idxprom = sext i32 %i.0 to i64
385 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
386 %0 = load i32, ptr %arrayidx, align 4
387 %add = add nsw i32 %sum.0, %0
388 %inc = add nsw i32 %i.0, 1
389 %cmp2 = icmp sle i32 %i.0, %b
390 br i1 %cmp2, label %for.cond, label %for.end
396 define i32 @test8(ptr %a, i32 %b, i32 %init) {
397 ; Note: %indvars.iv is the sign extension of %i.0
398 ; CHECK-LABEL: @test8(
400 ; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
401 ; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
402 ; CHECK: for.cond.preheader:
403 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INIT]] to i64
404 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[B:%.*]] to i64
405 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
407 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
408 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
409 ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP1]]
410 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
412 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
413 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
414 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
415 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
416 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 0, [[INDVARS_IV_NEXT]]
417 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
419 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
420 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
422 ; CHECK-NEXT: ret i32 0
425 %e = icmp sgt i32 %init, 0
426 br i1 %e, label %for.cond, label %leave
429 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
430 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
431 %cmp = icmp ule i32 %i.0, %b
432 br i1 %cmp, label %for.body, label %for.end
435 %idxprom = sext i32 %i.0 to i64
436 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
437 %0 = load i32, ptr %arrayidx, align 4
438 %add = add nsw i32 %sum.0, %0
439 %inc = add nsw i32 %i.0, 1
440 %cmp2 = icmp slt i32 0, %inc
441 br i1 %cmp2, label %for.cond, label %for.end
450 define i32 @test9(ptr %a, i32 %b, i32 %init) {
451 ; Note: %indvars.iv is the zero extension of %i.0
452 ; CHECK-LABEL: @test9(
454 ; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
455 ; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
456 ; CHECK: for.cond.preheader:
457 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[INIT]] to i64
458 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INIT]], i32 [[B:%.*]])
459 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
460 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
462 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
463 ; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
464 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]]
465 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
467 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
468 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
469 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
470 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
471 ; CHECK-NEXT: [[TMP2:%.*]] = trunc nuw i64 [[INDVARS_IV_NEXT]] to i32
472 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[TMP2]]
473 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
475 ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
476 ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
478 ; CHECK-NEXT: ret i32 0
481 %e = icmp sgt i32 %init, 0
482 br i1 %e, label %for.cond, label %leave
485 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
486 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
487 %cmp = icmp slt i32 %i.0, %b
488 br i1 %cmp, label %for.body, label %for.end
491 %idxprom = zext i32 %i.0 to i64
492 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom
493 %0 = load i32, ptr %arrayidx, align 4
494 %add = add nsw i32 %sum.0, %0
495 %inc = add nsw i32 %i.0, 1
496 %cmp2 = icmp slt i32 0, %inc
497 br i1 %cmp2, label %for.cond, label %for.end
506 declare void @consume.i64(i64)
507 declare void @consume.i1(i1)
509 define i32 @test10(i32 %v) {
510 ; CHECK-LABEL: @test10(
512 ; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[V:%.*]] to i64
513 ; CHECK-NEXT: br label [[LOOP:%.*]]
515 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
516 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
517 ; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVARS_IV]], -1
518 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], [[SEXT]]
519 ; CHECK-NEXT: call void @consume.i1(i1 [[TMP1]])
520 ; CHECK-NEXT: call void @consume.i64(i64 [[TMP0]])
521 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 11
522 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE:%.*]]
524 ; CHECK-NEXT: ret i32 22
531 %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
532 %i.inc = add i32 %i, 1
534 %cmp = icmp eq i32 %iv, %v
535 call void @consume.i1(i1 %cmp)
536 %be.cond = icmp slt i32 %i.inc, 11
537 %ext = sext i32 %iv to i64
538 call void @consume.i64(i64 %ext)
539 br i1 %be.cond, label %loop, label %leave
545 ; TODO: We don't really need trunc/zext here because when iv.next overflows,
546 ; its value is not used.
547 define i32 @test11(i32 %start, ptr %p, ptr %q) {
548 ; CHECK-LABEL: @test11(
550 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
551 ; CHECK-NEXT: br label [[LOOP:%.*]]
553 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
554 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
555 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
556 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
557 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
559 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
560 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
561 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
562 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
563 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
565 ; CHECK-NEXT: ret i32 0
567 ; CHECK-NEXT: unreachable
573 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
574 %iv.next = add i32 %iv, -1
575 %cond = icmp eq i32 %iv, 0
576 br i1 %cond, label %exit, label %backedge
579 %index = zext i32 %iv.next to i64
580 %store.addr = getelementptr i32, ptr %p, i64 %index
581 store i32 1, ptr %store.addr
582 %load.addr = getelementptr i32, ptr %q, i64 %index
583 %stop = load i32, ptr %q
584 %loop.cond = icmp eq i32 %stop, 0
585 br i1 %loop.cond, label %loop, label %failure
594 define i32 @test12(i32 %start, ptr %p, ptr %q) {
595 ; CHECK-LABEL: @test12(
597 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
598 ; CHECK-NEXT: br label [[LOOP:%.*]]
600 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
601 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
602 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
604 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
605 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
606 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
607 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
608 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
609 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
610 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
612 ; CHECK-NEXT: ret i32 0
614 ; CHECK-NEXT: unreachable
620 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
621 %cond = icmp eq i32 %iv, 0
622 br i1 %cond, label %exit, label %backedge
625 %iv.next = add i32 %iv, -1
626 %index = zext i32 %iv.next to i64
627 %store.addr = getelementptr i32, ptr %p, i64 %index
628 store i32 1, ptr %store.addr
629 %load.addr = getelementptr i32, ptr %q, i64 %index
630 %stop = load i32, ptr %q
631 %loop.cond = icmp eq i32 %stop, 0
632 br i1 %loop.cond, label %loop, label %failure
641 define i32 @test13(i32 %start, ptr %p, ptr %q) {
642 ; CHECK-LABEL: @test13(
644 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
645 ; CHECK-NEXT: br label [[LOOP:%.*]]
647 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
648 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
649 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
651 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
652 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
653 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
654 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
655 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
656 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
657 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
659 ; CHECK-NEXT: ret i32 0
661 ; CHECK-NEXT: unreachable
667 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
668 %cond = icmp eq i32 %iv, 0
669 br i1 %cond, label %exit, label %backedge
672 %foo = add i32 %iv, -1
673 %index = zext i32 %foo to i64
674 %store.addr = getelementptr i32, ptr %p, i64 %index
675 store i32 1, ptr %store.addr
676 %load.addr = getelementptr i32, ptr %q, i64 %index
677 %stop = load i32, ptr %q
678 %loop.cond = icmp eq i32 %stop, 0
679 %iv.next.1 = add i32 %iv, -1
680 br i1 %loop.cond, label %loop, label %failure
689 define i32 @test14(i32 %start, ptr %p, ptr %q) {
690 ; CHECK-LABEL: @test14(
692 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
693 ; CHECK-NEXT: br label [[LOOP:%.*]]
695 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
696 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
697 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
698 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
700 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
701 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
702 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
703 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
704 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
705 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
707 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
708 ; CHECK-NEXT: ret i32 [[TMP2]]
710 ; CHECK-NEXT: unreachable
716 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
717 %cond = icmp eq i32 %iv, 0
718 %foo = add i32 %iv, -1
719 br i1 %cond, label %exit, label %backedge
722 %index = zext i32 %foo to i64
723 %store.addr = getelementptr i32, ptr %p, i64 %index
724 store i32 1, ptr %store.addr
725 %load.addr = getelementptr i32, ptr %q, i64 %index
726 %stop = load i32, ptr %q
727 %loop.cond = icmp eq i32 %stop, 0
728 %iv.next.1 = add i32 %iv, -1
729 br i1 %loop.cond, label %loop, label %failure
738 declare void @test14a-callee(i1 %cond)
740 ; Same as @test14 but with unwind exit.
741 ; Trunc instructions must be added below the landing pad.
742 define i32 @test14a(i32 %start, ptr %p, ptr %q, i1 %c) personality i1 1 {
743 ; CHECK-LABEL: @test14a(
745 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
746 ; CHECK-NEXT: br label [[LOOP:%.*]]
748 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
749 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
750 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
751 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
753 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
754 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
755 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
756 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
757 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
758 ; CHECK-NEXT: invoke void @test14a-callee(i1 [[LOOP_COND]])
759 ; CHECK-NEXT: to label [[LOOP]] unwind label [[EXCEPTION:%.*]]
761 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
762 ; CHECK-NEXT: ret i32 [[TMP2]]
764 ; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
765 ; CHECK-NEXT: [[TMP3:%.*]] = landingpad i1
766 ; CHECK-NEXT: cleanup
767 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32
768 ; CHECK-NEXT: ret i32 [[TMP4]]
774 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
775 %cond = icmp eq i32 %iv, 0
776 %foo = add i32 %iv, -1
777 br i1 %cond, label %exit, label %backedge
780 %index = zext i32 %foo to i64
781 %store.addr = getelementptr i32, ptr %p, i64 %index
782 store i32 1, ptr %store.addr
783 %load.addr = getelementptr i32, ptr %q, i64 %index
784 %stop = load i32, ptr %q
785 %loop.cond = icmp eq i32 %stop, 0
786 %iv.next.1 = add i32 %iv, -1
787 invoke void @test14a-callee(i1 %loop.cond) to label %loop unwind label %exception
798 declare void @use(i32 %arg)
800 define i32 @test15(i32 %start, ptr %p, ptr %q) {
801 ; CHECK-LABEL: @test15(
803 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
804 ; CHECK-NEXT: br label [[LOOP:%.*]]
806 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
807 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
808 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
809 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
811 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
812 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
813 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
814 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
815 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
816 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
818 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
819 ; CHECK-NEXT: call void @use(i32 [[TMP2]])
820 ; CHECK-NEXT: ret i32 [[TMP2]]
822 ; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
823 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32
824 ; CHECK-NEXT: call void @use(i32 [[TMP3]])
825 ; CHECK-NEXT: unreachable
831 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
832 %cond = icmp eq i32 %iv, 0
833 %foo = add i32 %iv, -1
834 br i1 %cond, label %exit, label %backedge
837 %index = zext i32 %foo to i64
838 %store.addr = getelementptr i32, ptr %p, i64 %index
839 store i32 1, ptr %store.addr
840 %load.addr = getelementptr i32, ptr %q, i64 %index
841 %stop = load i32, ptr %q
842 %loop.cond = icmp eq i32 %stop, 0
843 %iv.next.1 = add i32 %iv, -1
844 br i1 %loop.cond, label %loop, label %failure
847 call void @use(i32 %foo)
851 call void @use(i32 %foo)
855 define i32 @test16_unsigned_pos1(i32 %start, ptr %p, ptr %q, i32 %x) {
856 ; CHECK-LABEL: @test16_unsigned_pos1(
858 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
859 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], -1
860 ; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X:%.*]] to i64
861 ; CHECK-NEXT: [[ICMP_USER_WIDE_FIRST_ITER:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]]
862 ; CHECK-NEXT: br label [[LOOP:%.*]]
864 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
865 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
866 ; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], -1
867 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
869 ; CHECK-NEXT: br i1 [[ICMP_USER_WIDE_FIRST_ITER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
871 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP3]]
872 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
873 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
874 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
875 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
876 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
878 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 -1 to i32
879 ; CHECK-NEXT: call void @use(i32 [[TMP4]])
880 ; CHECK-NEXT: ret i32 [[TMP4]]
882 ; CHECK-NEXT: [[FOO_LCSSA2_WIDE:%.*]] = phi i64 [ [[TMP3]], [[BACKEDGE]] ]
883 ; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[FOO_LCSSA2_WIDE]] to i32
884 ; CHECK-NEXT: call void @use(i32 [[TMP5]])
885 ; CHECK-NEXT: unreachable
887 ; CHECK-NEXT: ret i32 0
893 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
894 %cond = icmp eq i32 %iv, 0
895 %foo = add i32 %iv, -1
896 br i1 %cond, label %exit, label %guarded
899 %icmp_user = icmp ult i32 %foo, %x
900 br i1 %icmp_user, label %backedge, label %side_exit
903 %index = zext i32 %foo to i64
904 %store.addr = getelementptr i32, ptr %p, i64 %index
905 store i32 1, ptr %store.addr
906 %load.addr = getelementptr i32, ptr %q, i64 %index
907 %stop = load i32, ptr %q
908 %loop.cond = icmp eq i32 %stop, 0
909 %iv.next.1 = add i32 %iv, -1
910 br i1 %loop.cond, label %loop, label %failure
913 call void @use(i32 %foo)
917 call void @use(i32 %foo)
924 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
925 define i32 @test16_unsigned_pos2(i32 %start, ptr %p, ptr %q, i32 %x) {
926 ; CHECK-LABEL: @test16_unsigned_pos2(
928 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
929 ; CHECK-NEXT: br label [[LOOP:%.*]]
931 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
932 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
933 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
934 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
936 ; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X:%.*]] to i64
937 ; CHECK-NEXT: [[ICMP_USER_WIDE:%.*]] = icmp ne i64 [[TMP1]], [[TMP2]]
938 ; CHECK-NEXT: br i1 [[ICMP_USER_WIDE]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
940 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]]
941 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
942 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q:%.*]], align 4
943 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
944 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
945 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
947 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 -1 to i32
948 ; CHECK-NEXT: call void @use(i32 [[TMP3]])
949 ; CHECK-NEXT: ret i32 [[TMP3]]
951 ; CHECK-NEXT: [[FOO_LCSSA2_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ]
952 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[FOO_LCSSA2_WIDE]] to i32
953 ; CHECK-NEXT: call void @use(i32 [[TMP4]])
954 ; CHECK-NEXT: unreachable
956 ; CHECK-NEXT: ret i32 0
962 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
963 %cond = icmp eq i32 %iv, 0
964 %foo = add i32 %iv, -1
965 br i1 %cond, label %exit, label %guarded
968 %icmp_user = icmp ne i32 %foo, %x
969 br i1 %icmp_user, label %backedge, label %side_exit
972 %index = zext i32 %foo to i64
973 %store.addr = getelementptr i32, ptr %p, i64 %index
974 store i32 1, ptr %store.addr
975 %load.addr = getelementptr i32, ptr %q, i64 %index
976 %stop = load i32, ptr %q
977 %loop.cond = icmp eq i32 %stop, 0
978 %iv.next.1 = add i32 %iv, -1
979 br i1 %loop.cond, label %loop, label %failure
982 call void @use(i32 %foo)
986 call void @use(i32 %foo)
993 ; icmp slt user in guarded block prevents widening.
994 define i32 @test16_unsigned_neg(i32 %start, ptr %p, ptr %q, i32 %x) {
995 ; CHECK-LABEL: @test16_unsigned_neg(
997 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64
998 ; CHECK-NEXT: br label [[LOOP:%.*]]
1000 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
1001 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
1002 ; CHECK-NEXT: [[TMP1:%.*]] = trunc nuw i64 [[INDVARS_IV]] to i32
1003 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[TMP1]], -1
1004 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1006 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]]
1007 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1009 ; CHECK-NEXT: [[INDEX:%.*]] = zext i32 [[FOO]] to i64
1010 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1011 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1012 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1013 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1014 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1015 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
1016 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1018 ; CHECK-NEXT: call void @use(i32 -1)
1019 ; CHECK-NEXT: ret i32 -1
1021 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1022 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1023 ; CHECK-NEXT: unreachable
1025 ; CHECK-NEXT: ret i32 0
1031 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1032 %cond = icmp eq i32 %iv, 0
1033 %foo = add i32 %iv, -1
1034 br i1 %cond, label %exit, label %guarded
1037 %icmp_user = icmp slt i32 %foo, %x
1038 br i1 %icmp_user, label %backedge, label %side_exit
1041 %index = zext i32 %foo to i64
1042 %store.addr = getelementptr i32, ptr %p, i64 %index
1043 store i32 1, ptr %store.addr
1044 %load.addr = getelementptr i32, ptr %q, i64 %index
1045 %stop = load i32, ptr %q
1046 %loop.cond = icmp eq i32 %stop, 0
1047 %iv.next.1 = add i32 %iv, -1
1048 br i1 %loop.cond, label %loop, label %failure
1051 call void @use(i32 %foo)
1055 call void @use(i32 %foo)
1062 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
1063 define i32 @test16_signed_pos1(i32 %start, ptr %p, ptr %q, i32 %x) {
1064 ; CHECK-LABEL: @test16_signed_pos1(
1065 ; CHECK-NEXT: entry:
1066 ; CHECK-NEXT: br label [[LOOP:%.*]]
1068 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1069 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1070 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1071 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1073 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]]
1074 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1076 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1077 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1078 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1079 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1080 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1081 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1082 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1083 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1085 ; CHECK-NEXT: call void @use(i32 -1)
1086 ; CHECK-NEXT: ret i32 -1
1088 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1089 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1090 ; CHECK-NEXT: unreachable
1092 ; CHECK-NEXT: ret i32 0
1098 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1099 %cond = icmp eq i32 %iv, 0
1100 %foo = add i32 %iv, -1
1101 br i1 %cond, label %exit, label %guarded
1104 %icmp_user = icmp slt i32 %foo, %x
1105 br i1 %icmp_user, label %backedge, label %side_exit
1108 %index = sext i32 %foo to i64
1109 %store.addr = getelementptr i32, ptr %p, i64 %index
1110 store i32 1, ptr %store.addr
1111 %load.addr = getelementptr i32, ptr %q, i64 %index
1112 %stop = load i32, ptr %q
1113 %loop.cond = icmp eq i32 %stop, 0
1114 %iv.next.1 = add i32 %iv, -1
1115 br i1 %loop.cond, label %loop, label %failure
1118 call void @use(i32 %foo)
1122 call void @use(i32 %foo)
1129 ; TODO: We can widen here despite the icmp user of %foo in guarded block.
1130 define i32 @test16_signed_pos2(i32 %start, ptr %p, ptr %q, i32 %x) {
1131 ; CHECK-LABEL: @test16_signed_pos2(
1132 ; CHECK-NEXT: entry:
1133 ; CHECK-NEXT: br label [[LOOP:%.*]]
1135 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1136 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1137 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1138 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1140 ; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp ne i32 [[FOO]], [[X:%.*]]
1141 ; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1143 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1144 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1145 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1146 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1147 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1148 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1149 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1150 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1152 ; CHECK-NEXT: call void @use(i32 -1)
1153 ; CHECK-NEXT: ret i32 -1
1155 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1156 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1157 ; CHECK-NEXT: unreachable
1159 ; CHECK-NEXT: ret i32 0
1165 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1166 %cond = icmp eq i32 %iv, 0
1167 %foo = add i32 %iv, -1
1168 br i1 %cond, label %exit, label %guarded
1171 %icmp_user = icmp ne i32 %foo, %x
1172 br i1 %icmp_user, label %backedge, label %side_exit
1175 %index = sext i32 %foo to i64
1176 %store.addr = getelementptr i32, ptr %p, i64 %index
1177 store i32 1, ptr %store.addr
1178 %load.addr = getelementptr i32, ptr %q, i64 %index
1179 %stop = load i32, ptr %q
1180 %loop.cond = icmp eq i32 %stop, 0
1181 %iv.next.1 = add i32 %iv, -1
1182 br i1 %loop.cond, label %loop, label %failure
1185 call void @use(i32 %foo)
1189 call void @use(i32 %foo)
1196 ; icmp ult user in guarded block prevents widening.
1197 define i32 @test16_signed_neg(i32 %start, ptr %p, ptr %q, i32 %x) {
1198 ; CHECK-LABEL: @test16_signed_neg(
1199 ; CHECK-NEXT: entry:
1200 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
1201 ; CHECK-NEXT: [[ICMP_USER_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[X:%.*]]
1202 ; CHECK-NEXT: br label [[LOOP:%.*]]
1204 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ]
1205 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0
1206 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1
1207 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]]
1209 ; CHECK-NEXT: br i1 [[ICMP_USER_FIRST_ITER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]]
1211 ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64
1212 ; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1213 ; CHECK-NEXT: store i32 1, ptr [[STORE_ADDR]], align 4
1214 ; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, ptr [[Q:%.*]], i64 [[INDEX]]
1215 ; CHECK-NEXT: [[STOP:%.*]] = load i32, ptr [[Q]], align 4
1216 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
1217 ; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1
1218 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
1220 ; CHECK-NEXT: call void @use(i32 -1)
1221 ; CHECK-NEXT: ret i32 -1
1223 ; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ]
1224 ; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]])
1225 ; CHECK-NEXT: unreachable
1227 ; CHECK-NEXT: ret i32 0
1233 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge]
1234 %cond = icmp eq i32 %iv, 0
1235 %foo = add i32 %iv, -1
1236 br i1 %cond, label %exit, label %guarded
1239 %icmp_user = icmp ult i32 %foo, %x
1240 br i1 %icmp_user, label %backedge, label %side_exit
1243 %index = sext i32 %foo to i64
1244 %store.addr = getelementptr i32, ptr %p, i64 %index
1245 store i32 1, ptr %store.addr
1246 %load.addr = getelementptr i32, ptr %q, i64 %index
1247 %stop = load i32, ptr %q
1248 %loop.cond = icmp eq i32 %stop, 0
1249 %iv.next.1 = add i32 %iv, -1
1250 br i1 %loop.cond, label %loop, label %failure
1253 call void @use(i32 %foo)
1257 call void @use(i32 %foo)
1264 define i32 @test17(ptr %p, i32 %len) {
1265 ; CHECK-LABEL: @test17(
1266 ; CHECK-NEXT: entry:
1267 ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LEN:%.*]] to i64
1268 ; CHECK-NEXT: br label [[LOOP:%.*]]
1270 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
1271 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
1272 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
1273 ; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
1274 ; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
1276 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[TMP1]]
1277 ; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
1278 ; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], 0
1279 ; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
1281 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32
1282 ; CHECK-NEXT: ret i32 [[TMP2]]
1284 ; CHECK-NEXT: unreachable
1290 %iv = phi i32 [ %iv.next, %backedge ], [ %len, %entry ]
1291 %iv.next = add i32 %iv, -1
1292 %cond_1 = icmp eq i32 %iv, 0
1293 br i1 %cond_1, label %exit, label %backedge
1296 %iv.next.wide = zext i32 %iv.next to i64
1297 %addr = getelementptr inbounds i32, ptr %p, i64 %iv.next.wide
1298 %loaded = load atomic i32, ptr %addr unordered, align 4
1299 %cond_2 = icmp eq i32 %loaded, 0
1300 br i1 %cond_2, label %failure, label %loop
1309 declare void @foo(i64 %v)
1310 declare void @bar(i32 %v)
1312 define void @test18() {
1313 ; CHECK-LABEL: @test18(
1314 ; CHECK-NEXT: entry:
1315 ; CHECK-NEXT: br label [[LOOP:%.*]]
1317 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1318 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1319 ; CHECK-NEXT: [[INDVARS2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1320 ; CHECK-NEXT: call void @bar(i32 [[INDVARS2]])
1321 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1322 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1323 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1325 ; CHECK-NEXT: ret void
1330 loop: ; preds = %loop, %entry
1331 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1332 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ]
1333 %val1.inc = add i32 %val1, 1
1334 %iv.next = add i32 %iv, 1
1335 call void @bar(i32 %val1.inc)
1336 %iv.wide = zext i32 %iv to i64
1337 call void @foo(i64 %iv.wide)
1338 %loop.cond = icmp eq i32 %iv, 1000
1339 br i1 %loop.cond, label %exit, label %loop
1341 exit: ; preds = %loop
1345 define void @test19() {
1346 ; CHECK-LABEL: @test19(
1347 ; CHECK-NEXT: entry:
1348 ; CHECK-NEXT: br label [[LOOP:%.*]]
1350 ; CHECK-NEXT: [[VAL1:%.*]] = phi i64 [ [[VAL1_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1351 ; CHECK-NEXT: [[VAL1_INC]] = add nuw nsw i64 [[VAL1]], 1
1352 ; CHECK-NEXT: call void @foo(i64 [[VAL1_INC]])
1353 ; CHECK-NEXT: call void @foo(i64 [[VAL1]])
1354 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[VAL1]], 1000
1355 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1357 ; CHECK-NEXT: ret void
1362 loop: ; preds = %loop, %entry
1363 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1364 %val1 = phi i64 [ %val1.inc, %loop ], [ 0, %entry ]
1365 %val1.inc = add i64 %val1, 1
1366 %iv.next = add i32 %iv, 1
1367 call void @foo(i64 %val1.inc)
1368 %iv.wide = zext i32 %iv to i64
1369 call void @foo(i64 %iv.wide)
1370 %loop.cond = icmp eq i32 %iv, 1000
1371 br i1 %loop.cond, label %exit, label %loop
1373 exit: ; preds = %loop
1377 define void @test20() {
1378 ; CHECK-LABEL: @test20(
1379 ; CHECK-NEXT: entry:
1380 ; CHECK-NEXT: br label [[LOOP:%.*]]
1382 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1383 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1384 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1385 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1386 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1387 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1389 ; CHECK-NEXT: ret void
1394 loop: ; preds = %loop, %entry
1395 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1396 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ]
1397 %val1.inc = add i32 %val1, 1
1398 %iv.next = add i32 %iv, 1
1399 %val1.wide = zext i32 %val1 to i64
1400 call void @foo(i64 %val1.wide)
1401 %iv.wide = zext i32 %iv to i64
1402 call void @foo(i64 %iv.wide)
1403 %loop.cond = icmp eq i32 %iv, 1000
1404 br i1 %loop.cond, label %exit, label %loop
1406 exit: ; preds = %loop
1410 define void @test21(ptr %ptr) {
1411 ; CHECK-LABEL: @test21(
1412 ; CHECK-NEXT: entry:
1413 ; CHECK-NEXT: store i32 0, ptr [[PTR:%.*]], align 4
1414 ; CHECK-NEXT: br label [[LOOP:%.*]]
1416 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1417 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1418 ; CHECK-NEXT: [[INDVARS:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1419 ; CHECK-NEXT: store i32 [[INDVARS]], ptr [[PTR]], align 4
1420 ; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
1421 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
1422 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1424 ; CHECK-NEXT: ret void
1427 store i32 0, ptr %ptr, align 4
1430 loop: ; preds = %loop, %entry
1431 %val = phi i32 [ %val.inc, %loop ], [ 0, %entry ]
1432 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1433 %val.inc = add i32 %val, 1
1434 store i32 %val.inc, ptr %ptr, align 4
1435 %iv.wide = zext i32 %iv to i64
1436 call void @foo(i64 %iv.wide)
1437 %iv.next = add i32 %iv, 1
1438 %loop.cond = icmp eq i32 %iv, 1000
1439 br i1 %loop.cond, label %exit, label %loop
1441 exit: ; preds = %loop
1445 ; Don't perform replacement here; SCEV won't recognize the new PHI as an
1446 ; induction variable.
1447 define void @test22(ptr %ptr) {
1448 ; CHECK-LABEL: @test22(
1449 ; CHECK-NEXT: entry:
1450 ; CHECK-NEXT: store i16 0, ptr [[PTR:%.*]], align 4
1451 ; CHECK-NEXT: br label [[LOOP:%.*]]
1453 ; CHECK-NEXT: [[VAL:%.*]] = phi i16 [ [[VAL_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
1454 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ]
1455 ; CHECK-NEXT: [[VAL_INC]] = add i16 [[VAL]], 1
1456 ; CHECK-NEXT: store i16 [[VAL_INC]], ptr [[PTR]], align 4
1457 ; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
1458 ; CHECK-NEXT: call void @foo(i64 [[IV_WIDE]])
1459 ; CHECK-NEXT: [[IV_NEXT]] = zext i16 [[VAL_INC]] to i32
1460 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[IV]], 1000
1461 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
1463 ; CHECK-NEXT: ret void
1466 store i16 0, ptr %ptr, align 4
1469 loop: ; preds = %loop, %entry
1470 %val = phi i16 [ %val.inc, %loop ], [ 0, %entry ]
1471 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
1472 %val.inc = add i16 %val, 1
1473 store i16 %val.inc, ptr %ptr, align 4
1474 %iv.wide = zext i32 %iv to i64
1475 call void @foo(i64 %iv.wide)
1476 %iv.next = zext i16 %val.inc to i32
1477 %loop.cond = icmp eq i32 %iv, 1000
1478 br i1 %loop.cond, label %exit, label %loop
1480 exit: ; preds = %loop