1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=loop-vectorize -force-vector-width=2 < %s | FileCheck %s
3 ; RUN: opt -S -passes=loop-vectorize -force-vector-width=2 -prefer-predicate-over-epilogue=predicate-dont-vectorize < %s | FileCheck --check-prefix TAILFOLD %s
5 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
7 define void @bottom_tested(ptr %p, i32 %n) {
8 ; CHECK-LABEL: @bottom_tested(
10 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
11 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1
12 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 2
13 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
15 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
16 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[N_MOD_VF]]
17 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
19 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
20 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[INDEX]], 0
21 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
22 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP2]]
23 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i16, ptr [[TMP3]], i32 0
24 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP4]], align 4
25 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
26 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
27 ; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
28 ; CHECK: middle.block:
29 ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP0]], [[N_VEC]]
30 ; CHECK-NEXT: br i1 [[CMP_N]], label [[IF_END:%.*]], label [[SCALAR_PH]]
32 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
33 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
35 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_COND]] ]
36 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
37 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
38 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
39 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
40 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
41 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[IF_END]], !llvm.loop [[LOOP3:![0-9]+]]
43 ; CHECK-NEXT: ret void
45 ; TAILFOLD-LABEL: @bottom_tested(
46 ; TAILFOLD-NEXT: entry:
47 ; TAILFOLD-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
48 ; TAILFOLD-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1
49 ; TAILFOLD-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
50 ; TAILFOLD: vector.ph:
51 ; TAILFOLD-NEXT: [[N_RND_UP:%.*]] = add i32 [[TMP0]], 1
52 ; TAILFOLD-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N_RND_UP]], 2
53 ; TAILFOLD-NEXT: [[N_VEC:%.*]] = sub i32 [[N_RND_UP]], [[N_MOD_VF]]
54 ; TAILFOLD-NEXT: [[TRIP_COUNT_MINUS_1:%.*]] = sub i32 [[TMP0]], 1
55 ; TAILFOLD-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i32> poison, i32 [[TRIP_COUNT_MINUS_1]], i64 0
56 ; TAILFOLD-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i32> [[BROADCAST_SPLATINSERT]], <2 x i32> poison, <2 x i32> zeroinitializer
57 ; TAILFOLD-NEXT: br label [[VECTOR_BODY:%.*]]
58 ; TAILFOLD: vector.body:
59 ; TAILFOLD-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE2:%.*]] ]
60 ; TAILFOLD-NEXT: [[VEC_IND:%.*]] = phi <2 x i32> [ <i32 0, i32 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_STORE_CONTINUE2]] ]
61 ; TAILFOLD-NEXT: [[TMP1:%.*]] = icmp ule <2 x i32> [[VEC_IND]], [[BROADCAST_SPLAT]]
62 ; TAILFOLD-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[VEC_IND]] to <2 x i64>
63 ; TAILFOLD-NEXT: [[TMP3:%.*]] = extractelement <2 x i1> [[TMP1]], i32 0
64 ; TAILFOLD-NEXT: br i1 [[TMP3]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]]
65 ; TAILFOLD: pred.store.if:
66 ; TAILFOLD-NEXT: [[TMP4:%.*]] = extractelement <2 x i64> [[TMP2]], i32 0
67 ; TAILFOLD-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
68 ; TAILFOLD-NEXT: store i16 0, ptr [[TMP5]], align 4
69 ; TAILFOLD-NEXT: br label [[PRED_STORE_CONTINUE]]
70 ; TAILFOLD: pred.store.continue:
71 ; TAILFOLD-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP1]], i32 1
72 ; TAILFOLD-NEXT: br i1 [[TMP6]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2]]
73 ; TAILFOLD: pred.store.if1:
74 ; TAILFOLD-NEXT: [[TMP7:%.*]] = extractelement <2 x i64> [[TMP2]], i32 1
75 ; TAILFOLD-NEXT: [[TMP8:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[TMP7]]
76 ; TAILFOLD-NEXT: store i16 0, ptr [[TMP8]], align 4
77 ; TAILFOLD-NEXT: br label [[PRED_STORE_CONTINUE2]]
78 ; TAILFOLD: pred.store.continue2:
79 ; TAILFOLD-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
80 ; TAILFOLD-NEXT: [[VEC_IND_NEXT]] = add <2 x i32> [[VEC_IND]], splat (i32 2)
81 ; TAILFOLD-NEXT: [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
82 ; TAILFOLD-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
83 ; TAILFOLD: middle.block:
84 ; TAILFOLD-NEXT: br i1 true, label [[IF_END:%.*]], label [[SCALAR_PH]]
85 ; TAILFOLD: scalar.ph:
86 ; TAILFOLD-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
87 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
89 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_COND]] ]
90 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
91 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
92 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
93 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
94 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
95 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[IF_END]], !llvm.loop [[LOOP3:![0-9]+]]
97 ; TAILFOLD-NEXT: ret void
103 %i = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
104 %iprom = sext i32 %i to i64
105 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
106 store i16 0, ptr %b, align 4
107 %inc = add nsw i32 %i, 1
108 %cmp = icmp slt i32 %i, %n
109 br i1 %cmp, label %for.cond, label %if.end
115 define void @early_exit(ptr %p, i32 %n) {
116 ; CHECK-LABEL: @early_exit(
118 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
119 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1
120 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
121 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
123 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
124 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
125 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
126 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
127 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
128 ; CHECK: vector.body:
129 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
130 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
131 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
132 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
133 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
134 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
135 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
136 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
137 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
138 ; CHECK: middle.block:
139 ; CHECK-NEXT: br label [[SCALAR_PH]]
141 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
142 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
144 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
145 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
146 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
148 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
149 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
150 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
151 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
152 ; CHECK-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]]
154 ; CHECK-NEXT: ret void
156 ; TAILFOLD-LABEL: @early_exit(
157 ; TAILFOLD-NEXT: entry:
158 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
159 ; TAILFOLD: for.cond:
160 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
161 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
162 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
163 ; TAILFOLD: for.body:
164 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
165 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
166 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
167 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
168 ; TAILFOLD-NEXT: br label [[FOR_COND]]
170 ; TAILFOLD-NEXT: ret void
176 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
177 %cmp = icmp slt i32 %i, %n
178 br i1 %cmp, label %for.body, label %if.end
181 %iprom = sext i32 %i to i64
182 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
183 store i16 0, ptr %b, align 4
184 %inc = add nsw i32 %i, 1
191 define i32 @early_exit_with_live_out(ptr %ptr) {
192 ; CHECK-LABEL: @early_exit_with_live_out(
194 ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
196 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
197 ; CHECK: vector.body:
198 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
199 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
200 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i64 [[TMP0]]
201 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], i32 0
202 ; CHECK-NEXT: store <2 x i32> splat (i32 10), ptr [[TMP2]], align 4
203 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
204 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 998
205 ; CHECK-NEXT: br i1 [[TMP3]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
206 ; CHECK: middle.block:
207 ; CHECK-NEXT: br label [[SCALAR_PH]]
209 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 998, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
210 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
211 ; CHECK: loop.header:
212 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
213 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[IV]]
214 ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4
215 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
216 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
217 ; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
219 ; CHECK-NEXT: store i32 10, ptr [[GEP]], align 4
220 ; CHECK-NEXT: br label [[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]
222 ; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[L]], [[LOOP_HEADER]] ]
223 ; CHECK-NEXT: ret i32 [[RES_LCSSA]]
225 ; TAILFOLD-LABEL: @early_exit_with_live_out(
226 ; TAILFOLD-NEXT: entry:
227 ; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]]
228 ; TAILFOLD: loop.header:
229 ; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
230 ; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i64 [[IV]]
231 ; TAILFOLD-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4
232 ; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
233 ; TAILFOLD-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
234 ; TAILFOLD-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
235 ; TAILFOLD: loop.latch:
236 ; TAILFOLD-NEXT: store i32 10, ptr [[GEP]], align 4
237 ; TAILFOLD-NEXT: br label [[LOOP_HEADER]]
239 ; TAILFOLD-NEXT: [[RES_LCSSA:%.*]] = phi i32 [ [[L]], [[LOOP_HEADER]] ]
240 ; TAILFOLD-NEXT: ret i32 [[RES_LCSSA]]
243 br label %loop.header
246 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
247 %gep = getelementptr i32, ptr %ptr, i64 %iv
248 %l = load i32, ptr %gep
249 %iv.next = add nuw nsw i64 %iv, 1
250 %ec = icmp eq i64 %iv.next, 1000
251 br i1 %ec, label %exit, label %loop.latch
254 store i32 10, ptr %gep
255 br label %loop.header
258 %res.lcssa = phi i32 [ %l, %loop.header ]
262 ; Same as early_exit, but with optsize to prevent the use of
263 ; a scalar epilogue. -- Can't vectorize this in either case.
264 define void @optsize(ptr %p, i32 %n) optsize {
265 ; CHECK-LABEL: @optsize(
267 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
269 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
270 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
271 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
273 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
274 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
275 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
276 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
277 ; CHECK-NEXT: br label [[FOR_COND]]
279 ; CHECK-NEXT: ret void
281 ; TAILFOLD-LABEL: @optsize(
282 ; TAILFOLD-NEXT: entry:
283 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
284 ; TAILFOLD: for.cond:
285 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
286 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
287 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
288 ; TAILFOLD: for.body:
289 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
290 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
291 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
292 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
293 ; TAILFOLD-NEXT: br label [[FOR_COND]]
295 ; TAILFOLD-NEXT: ret void
301 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
302 %cmp = icmp slt i32 %i, %n
303 br i1 %cmp, label %for.body, label %if.end
306 %iprom = sext i32 %i to i64
307 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
308 store i16 0, ptr %b, align 4
309 %inc = add nsw i32 %i, 1
317 ; multiple exit - no values inside the loop used outside
318 define void @multiple_unique_exit(ptr %p, i32 %n) {
319 ; CHECK-LABEL: @multiple_unique_exit(
321 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
322 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
323 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
324 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
325 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
327 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
328 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
329 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
330 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
331 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
332 ; CHECK: vector.body:
333 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
334 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
335 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
336 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
337 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
338 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
339 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
340 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
341 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
342 ; CHECK: middle.block:
343 ; CHECK-NEXT: br label [[SCALAR_PH]]
345 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
346 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
348 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
349 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
350 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
352 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
353 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
354 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
355 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
356 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
357 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]], !llvm.loop [[LOOP9:![0-9]+]]
359 ; CHECK-NEXT: ret void
361 ; TAILFOLD-LABEL: @multiple_unique_exit(
362 ; TAILFOLD-NEXT: entry:
363 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
364 ; TAILFOLD: for.cond:
365 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
366 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
367 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
368 ; TAILFOLD: for.body:
369 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
370 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
371 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
372 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
373 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
374 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]]
376 ; TAILFOLD-NEXT: ret void
382 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
383 %cmp = icmp slt i32 %i, %n
384 br i1 %cmp, label %for.body, label %if.end
387 %iprom = sext i32 %i to i64
388 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
389 store i16 0, ptr %b, align 4
390 %inc = add nsw i32 %i, 1
391 %cmp2 = icmp slt i32 %i, 2096
392 br i1 %cmp2, label %for.cond, label %if.end
398 ; multiple exit - with an lcssa phi
399 define i32 @multiple_unique_exit2(ptr %p, i32 %n) {
400 ; CHECK-LABEL: @multiple_unique_exit2(
402 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
403 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
404 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
405 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
406 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
408 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
409 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
410 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
411 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
412 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
413 ; CHECK: vector.body:
414 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
415 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
416 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
417 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
418 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
419 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
420 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
421 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
422 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]]
423 ; CHECK: middle.block:
424 ; CHECK-NEXT: br label [[SCALAR_PH]]
426 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
427 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
429 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
430 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
431 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
433 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
434 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
435 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
436 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
437 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
438 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]], !llvm.loop [[LOOP11:![0-9]+]]
440 ; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_BODY]] ], [ [[I]], [[FOR_COND]] ]
441 ; CHECK-NEXT: ret i32 [[I_LCSSA]]
443 ; TAILFOLD-LABEL: @multiple_unique_exit2(
444 ; TAILFOLD-NEXT: entry:
445 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
446 ; TAILFOLD: for.cond:
447 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
448 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
449 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
450 ; TAILFOLD: for.body:
451 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
452 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
453 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
454 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
455 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
456 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]]
458 ; TAILFOLD-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_BODY]] ], [ [[I]], [[FOR_COND]] ]
459 ; TAILFOLD-NEXT: ret i32 [[I_LCSSA]]
465 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
466 %cmp = icmp slt i32 %i, %n
467 br i1 %cmp, label %for.body, label %if.end
470 %iprom = sext i32 %i to i64
471 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
472 store i16 0, ptr %b, align 4
473 %inc = add nsw i32 %i, 1
474 %cmp2 = icmp slt i32 %i, 2096
475 br i1 %cmp2, label %for.cond, label %if.end
481 ; multiple exit w/a non lcssa phi
482 define i32 @multiple_unique_exit3(ptr %p, i32 %n) {
483 ; CHECK-LABEL: @multiple_unique_exit3(
485 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
486 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
487 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
488 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
489 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
491 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
492 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
493 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
494 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
495 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
496 ; CHECK: vector.body:
497 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
498 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
499 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
500 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
501 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
502 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
503 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
504 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
505 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]
506 ; CHECK: middle.block:
507 ; CHECK-NEXT: br label [[SCALAR_PH]]
509 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
510 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
512 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
513 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
514 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
516 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
517 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
518 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
519 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
520 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
521 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]], !llvm.loop [[LOOP13:![0-9]+]]
523 ; CHECK-NEXT: [[EXIT:%.*]] = phi i32 [ 0, [[FOR_COND]] ], [ 1, [[FOR_BODY]] ]
524 ; CHECK-NEXT: ret i32 [[EXIT]]
526 ; TAILFOLD-LABEL: @multiple_unique_exit3(
527 ; TAILFOLD-NEXT: entry:
528 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
529 ; TAILFOLD: for.cond:
530 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
531 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
532 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
533 ; TAILFOLD: for.body:
534 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
535 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
536 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
537 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
538 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
539 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]]
541 ; TAILFOLD-NEXT: [[EXIT:%.*]] = phi i32 [ 0, [[FOR_COND]] ], [ 1, [[FOR_BODY]] ]
542 ; TAILFOLD-NEXT: ret i32 [[EXIT]]
548 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
549 %cmp = icmp slt i32 %i, %n
550 br i1 %cmp, label %for.body, label %if.end
553 %iprom = sext i32 %i to i64
554 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
555 store i16 0, ptr %b, align 4
556 %inc = add nsw i32 %i, 1
557 %cmp2 = icmp slt i32 %i, 2096
558 br i1 %cmp2, label %for.cond, label %if.end
561 %exit = phi i32 [0, %for.cond], [1, %for.body]
565 ; multiple exits w/distinct target blocks
566 define i32 @multiple_exit_blocks(ptr %p, i32 %n) {
567 ; CHECK-LABEL: @multiple_exit_blocks(
569 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
570 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
571 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
572 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
573 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
575 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
576 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
577 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
578 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
579 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
580 ; CHECK: vector.body:
581 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
582 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
583 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
584 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
585 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
586 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
587 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
588 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
589 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]]
590 ; CHECK: middle.block:
591 ; CHECK-NEXT: br label [[SCALAR_PH]]
593 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
594 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
596 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
597 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
598 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
600 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
601 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
602 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
603 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
604 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
605 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]], !llvm.loop [[LOOP15:![0-9]+]]
607 ; CHECK-NEXT: ret i32 0
609 ; CHECK-NEXT: ret i32 1
611 ; TAILFOLD-LABEL: @multiple_exit_blocks(
612 ; TAILFOLD-NEXT: entry:
613 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
614 ; TAILFOLD: for.cond:
615 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
616 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
617 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
618 ; TAILFOLD: for.body:
619 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
620 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
621 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
622 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
623 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
624 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]]
626 ; TAILFOLD-NEXT: ret i32 0
628 ; TAILFOLD-NEXT: ret i32 1
634 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
635 %cmp = icmp slt i32 %i, %n
636 br i1 %cmp, label %for.body, label %if.end
639 %iprom = sext i32 %i to i64
640 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
641 store i16 0, ptr %b, align 4
642 %inc = add nsw i32 %i, 1
643 %cmp2 = icmp slt i32 %i, 2096
644 br i1 %cmp2, label %for.cond, label %if.end2
653 ; LCSSA, common value each exit
654 define i32 @multiple_exit_blocks2(ptr %p, i32 %n) {
655 ; CHECK-LABEL: @multiple_exit_blocks2(
657 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
658 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
659 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
660 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
661 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
663 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
664 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
665 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
666 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
667 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
668 ; CHECK: vector.body:
669 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
670 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
671 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
672 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
673 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
674 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
675 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
676 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
677 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]]
678 ; CHECK: middle.block:
679 ; CHECK-NEXT: br label [[SCALAR_PH]]
681 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
682 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
684 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
685 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
686 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
688 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
689 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
690 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
691 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
692 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
693 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]], !llvm.loop [[LOOP17:![0-9]+]]
695 ; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ]
696 ; CHECK-NEXT: ret i32 [[I_LCSSA]]
698 ; CHECK-NEXT: [[I_LCSSA1:%.*]] = phi i32 [ [[I]], [[FOR_BODY]] ]
699 ; CHECK-NEXT: ret i32 [[I_LCSSA1]]
701 ; TAILFOLD-LABEL: @multiple_exit_blocks2(
702 ; TAILFOLD-NEXT: entry:
703 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
704 ; TAILFOLD: for.cond:
705 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
706 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
707 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
708 ; TAILFOLD: for.body:
709 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
710 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
711 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
712 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
713 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
714 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]]
716 ; TAILFOLD-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ]
717 ; TAILFOLD-NEXT: ret i32 [[I_LCSSA]]
719 ; TAILFOLD-NEXT: [[I_LCSSA1:%.*]] = phi i32 [ [[I]], [[FOR_BODY]] ]
720 ; TAILFOLD-NEXT: ret i32 [[I_LCSSA1]]
726 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
727 %cmp = icmp slt i32 %i, %n
728 br i1 %cmp, label %for.body, label %if.end
731 %iprom = sext i32 %i to i64
732 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
733 store i16 0, ptr %b, align 4
734 %inc = add nsw i32 %i, 1
735 %cmp2 = icmp slt i32 %i, 2096
736 br i1 %cmp2, label %for.cond, label %if.end2
745 ; LCSSA, distinct value each exit
746 define i32 @multiple_exit_blocks3(ptr %p, i32 %n) {
747 ; CHECK-LABEL: @multiple_exit_blocks3(
749 ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
750 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 2096)
751 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[UMIN]], 1
752 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP0]], 2
753 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
755 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 2
756 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
757 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 2, i32 [[N_MOD_VF]]
758 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[TMP2]]
759 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
760 ; CHECK: vector.body:
761 ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
762 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[INDEX]], 0
763 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64
764 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[TMP4]]
765 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
766 ; CHECK-NEXT: store <2 x i16> zeroinitializer, ptr [[TMP6]], align 4
767 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
768 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
769 ; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]]
770 ; CHECK: middle.block:
771 ; CHECK-NEXT: br label [[SCALAR_PH]]
773 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
774 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
776 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
777 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N]]
778 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
780 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
781 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IPROM]]
782 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
783 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
784 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
785 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]], !llvm.loop [[LOOP19:![0-9]+]]
787 ; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ]
788 ; CHECK-NEXT: ret i32 [[I_LCSSA]]
790 ; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[FOR_BODY]] ]
791 ; CHECK-NEXT: ret i32 [[INC_LCSSA]]
793 ; TAILFOLD-LABEL: @multiple_exit_blocks3(
794 ; TAILFOLD-NEXT: entry:
795 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
796 ; TAILFOLD: for.cond:
797 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
798 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]]
799 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]]
800 ; TAILFOLD: for.body:
801 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
802 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
803 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
804 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
805 ; TAILFOLD-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096
806 ; TAILFOLD-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END2:%.*]]
808 ; TAILFOLD-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ]
809 ; TAILFOLD-NEXT: ret i32 [[I_LCSSA]]
811 ; TAILFOLD-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[FOR_BODY]] ]
812 ; TAILFOLD-NEXT: ret i32 [[INC_LCSSA]]
818 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
819 %cmp = icmp slt i32 %i, %n
820 br i1 %cmp, label %for.body, label %if.end
823 %iprom = sext i32 %i to i64
824 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
825 store i16 0, ptr %b, align 4
826 %inc = add nsw i32 %i, 1
827 %cmp2 = icmp slt i32 %i, 2096
828 br i1 %cmp2, label %for.cond, label %if.end2
837 ; unique exit case but with a switch as two edges between the same pair of
838 ; blocks is an often missed edge case
839 define i32 @multiple_exit_switch(ptr %p, i32 %n) {
840 ; CHECK-LABEL: @multiple_exit_switch(
842 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
844 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND]] ]
845 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
846 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
847 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
848 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
849 ; CHECK-NEXT: switch i32 [[I]], label [[FOR_COND]] [
850 ; CHECK-NEXT: i32 2096, label [[IF_END:%.*]]
851 ; CHECK-NEXT: i32 2097, label [[IF_END]]
854 ; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ], [ [[I]], [[FOR_COND]] ]
855 ; CHECK-NEXT: ret i32 [[I_LCSSA]]
857 ; TAILFOLD-LABEL: @multiple_exit_switch(
858 ; TAILFOLD-NEXT: entry:
859 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
860 ; TAILFOLD: for.cond:
861 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND]] ]
862 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
863 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
864 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
865 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
866 ; TAILFOLD-NEXT: switch i32 [[I]], label [[FOR_COND]] [
867 ; TAILFOLD-NEXT: i32 2096, label [[IF_END:%.*]]
868 ; TAILFOLD-NEXT: i32 2097, label [[IF_END]]
871 ; TAILFOLD-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[FOR_COND]] ], [ [[I]], [[FOR_COND]] ]
872 ; TAILFOLD-NEXT: ret i32 [[I_LCSSA]]
878 %i = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
879 %iprom = sext i32 %i to i64
880 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
881 store i16 0, ptr %b, align 4
882 %inc = add nsw i32 %i, 1
883 switch i32 %i, label %for.cond [
884 i32 2096, label %if.end
885 i32 2097, label %if.end
892 ; multiple exit case but with a switch as multiple exiting edges from
893 ; a single block is a commonly missed edge case
894 define i32 @multiple_exit_switch2(ptr %p, i32 %n) {
895 ; CHECK-LABEL: @multiple_exit_switch2(
897 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
899 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND]] ]
900 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
901 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
902 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
903 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1
904 ; CHECK-NEXT: switch i32 [[I]], label [[FOR_COND]] [
905 ; CHECK-NEXT: i32 2096, label [[IF_END:%.*]]
906 ; CHECK-NEXT: i32 2097, label [[IF_END2:%.*]]
909 ; CHECK-NEXT: ret i32 0
911 ; CHECK-NEXT: ret i32 1
913 ; TAILFOLD-LABEL: @multiple_exit_switch2(
914 ; TAILFOLD-NEXT: entry:
915 ; TAILFOLD-NEXT: br label [[FOR_COND:%.*]]
916 ; TAILFOLD: for.cond:
917 ; TAILFOLD-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND]] ]
918 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64
919 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
920 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
921 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I]], 1
922 ; TAILFOLD-NEXT: switch i32 [[I]], label [[FOR_COND]] [
923 ; TAILFOLD-NEXT: i32 2096, label [[IF_END:%.*]]
924 ; TAILFOLD-NEXT: i32 2097, label [[IF_END2:%.*]]
927 ; TAILFOLD-NEXT: ret i32 0
929 ; TAILFOLD-NEXT: ret i32 1
935 %i = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
936 %iprom = sext i32 %i to i64
937 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
938 store i16 0, ptr %b, align 4
939 %inc = add nsw i32 %i, 1
940 switch i32 %i, label %for.cond [
941 i32 2096, label %if.end
942 i32 2097, label %if.end2
952 define i32 @multiple_latch1(ptr %p) {
953 ; CHECK-LABEL: @multiple_latch1(
955 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
957 ; CHECK-NEXT: [[I_02:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
958 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_02]], 1
959 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 16
960 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[FOR_SECOND:%.*]]
962 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I_02]] to i64
963 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
964 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
965 ; CHECK-NEXT: [[CMPS:%.*]] = icmp sgt i32 [[INC]], 16
966 ; CHECK-NEXT: br i1 [[CMPS]], label [[FOR_BODY_BACKEDGE]], label [[FOR_END:%.*]]
967 ; CHECK: for.body.backedge:
968 ; CHECK-NEXT: br label [[FOR_BODY]]
970 ; CHECK-NEXT: ret i32 0
972 ; TAILFOLD-LABEL: @multiple_latch1(
973 ; TAILFOLD-NEXT: entry:
974 ; TAILFOLD-NEXT: br label [[FOR_BODY:%.*]]
975 ; TAILFOLD: for.body:
976 ; TAILFOLD-NEXT: [[I_02:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
977 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I_02]], 1
978 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 16
979 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[FOR_SECOND:%.*]]
980 ; TAILFOLD: for.second:
981 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I_02]] to i64
982 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
983 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
984 ; TAILFOLD-NEXT: [[CMPS:%.*]] = icmp sgt i32 [[INC]], 16
985 ; TAILFOLD-NEXT: br i1 [[CMPS]], label [[FOR_BODY_BACKEDGE]], label [[FOR_END:%.*]]
986 ; TAILFOLD: for.body.backedge:
987 ; TAILFOLD-NEXT: br label [[FOR_BODY]]
989 ; TAILFOLD-NEXT: ret i32 0
995 %i.02 = phi i32 [ 0, %entry ], [ %inc, %for.body.backedge]
996 %inc = add nsw i32 %i.02, 1
997 %cmp = icmp slt i32 %inc, 16
998 br i1 %cmp, label %for.body.backedge, label %for.second
1001 %iprom = sext i32 %i.02 to i64
1002 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
1003 store i16 0, ptr %b, align 4
1004 %cmps = icmp sgt i32 %inc, 16
1005 br i1 %cmps, label %for.body.backedge, label %for.end
1015 ; two back branches - loop simplify with convert this to the same form
1016 ; as previous before vectorizer sees it, but show that.
1017 define i32 @multiple_latch2(ptr %p) {
1018 ; CHECK-LABEL: @multiple_latch2(
1019 ; CHECK-NEXT: entry:
1020 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
1022 ; CHECK-NEXT: [[I_02:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
1023 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_02]], 1
1024 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 16
1025 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[FOR_SECOND:%.*]]
1026 ; CHECK: for.body.backedge:
1027 ; CHECK-NEXT: br label [[FOR_BODY]]
1028 ; CHECK: for.second:
1029 ; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I_02]] to i64
1030 ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
1031 ; CHECK-NEXT: store i16 0, ptr [[B]], align 4
1032 ; CHECK-NEXT: [[CMPS:%.*]] = icmp sgt i32 [[INC]], 16
1033 ; CHECK-NEXT: br i1 [[CMPS]], label [[FOR_BODY_BACKEDGE]], label [[FOR_END:%.*]]
1035 ; CHECK-NEXT: ret i32 0
1037 ; TAILFOLD-LABEL: @multiple_latch2(
1038 ; TAILFOLD-NEXT: entry:
1039 ; TAILFOLD-NEXT: br label [[FOR_BODY:%.*]]
1040 ; TAILFOLD: for.body:
1041 ; TAILFOLD-NEXT: [[I_02:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
1042 ; TAILFOLD-NEXT: [[INC]] = add nsw i32 [[I_02]], 1
1043 ; TAILFOLD-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 16
1044 ; TAILFOLD-NEXT: br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[FOR_SECOND:%.*]]
1045 ; TAILFOLD: for.body.backedge:
1046 ; TAILFOLD-NEXT: br label [[FOR_BODY]]
1047 ; TAILFOLD: for.second:
1048 ; TAILFOLD-NEXT: [[IPROM:%.*]] = sext i32 [[I_02]] to i64
1049 ; TAILFOLD-NEXT: [[B:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IPROM]]
1050 ; TAILFOLD-NEXT: store i16 0, ptr [[B]], align 4
1051 ; TAILFOLD-NEXT: [[CMPS:%.*]] = icmp sgt i32 [[INC]], 16
1052 ; TAILFOLD-NEXT: br i1 [[CMPS]], label [[FOR_BODY_BACKEDGE]], label [[FOR_END:%.*]]
1053 ; TAILFOLD: for.end:
1054 ; TAILFOLD-NEXT: ret i32 0
1060 %i.02 = phi i32 [ 0, %entry ], [ %inc, %for.body ], [%inc, %for.second]
1061 %inc = add nsw i32 %i.02, 1
1062 %cmp = icmp slt i32 %inc, 16
1063 br i1 %cmp, label %for.body, label %for.second
1066 %iprom = sext i32 %i.02 to i64
1067 %b = getelementptr inbounds i16, ptr %p, i64 %iprom
1068 store i16 0, ptr %b, align 4
1069 %cmps = icmp sgt i32 %inc, 16
1070 br i1 %cmps, label %for.body, label %for.end
1077 ; Check interaction between block predication and early exits. We need the
1078 ; condition on the early exit to remain dead (i.e. not be used when forming
1079 ; the predicate mask).
1080 define void @scalar_predication(ptr %addr) {
1081 ; CHECK-LABEL: @scalar_predication(
1082 ; CHECK-NEXT: entry:
1083 ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
1085 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
1086 ; CHECK: vector.body:
1087 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE2:%.*]] ]
1088 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
1089 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr float, ptr [[ADDR:%.*]], i64 [[TMP0]]
1090 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr float, ptr [[TMP1]], i32 0
1091 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x float>, ptr [[TMP2]], align 4
1092 ; CHECK-NEXT: [[TMP3:%.*]] = fcmp oeq <2 x float> [[WIDE_LOAD]], zeroinitializer
1093 ; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1094 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1095 ; CHECK-NEXT: br i1 [[TMP5]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]]
1096 ; CHECK: pred.store.if:
1097 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr float, ptr [[ADDR]], i64 [[TMP0]]
1098 ; CHECK-NEXT: store float 1.000000e+01, ptr [[TMP6]], align 4
1099 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]]
1100 ; CHECK: pred.store.continue:
1101 ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1102 ; CHECK-NEXT: br i1 [[TMP7]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2]]
1103 ; CHECK: pred.store.if1:
1104 ; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[INDEX]], 1
1105 ; CHECK-NEXT: [[TMP9:%.*]] = getelementptr float, ptr [[ADDR]], i64 [[TMP8]]
1106 ; CHECK-NEXT: store float 1.000000e+01, ptr [[TMP9]], align 4
1107 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE2]]
1108 ; CHECK: pred.store.continue2:
1109 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1110 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 200
1111 ; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]]
1112 ; CHECK: middle.block:
1113 ; CHECK-NEXT: br label [[SCALAR_PH]]
1115 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 200, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
1116 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
1117 ; CHECK: loop.header:
1118 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1119 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, ptr [[ADDR]], i64 [[IV]]
1120 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1121 ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
1123 ; CHECK-NEXT: [[TMP11:%.*]] = load float, ptr [[GEP]], align 4
1124 ; CHECK-NEXT: [[PRED:%.*]] = fcmp oeq float [[TMP11]], 0.000000e+00
1125 ; CHECK-NEXT: br i1 [[PRED]], label [[LOOP_LATCH]], label [[THEN:%.*]]
1127 ; CHECK-NEXT: store float 1.000000e+01, ptr [[GEP]], align 4
1128 ; CHECK-NEXT: br label [[LOOP_LATCH]]
1129 ; CHECK: loop.latch:
1130 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1131 ; CHECK-NEXT: br label [[LOOP_HEADER]], !llvm.loop [[LOOP21:![0-9]+]]
1133 ; CHECK-NEXT: ret void
1135 ; TAILFOLD-LABEL: @scalar_predication(
1136 ; TAILFOLD-NEXT: entry:
1137 ; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]]
1138 ; TAILFOLD: loop.header:
1139 ; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1140 ; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr float, ptr [[ADDR:%.*]], i64 [[IV]]
1141 ; TAILFOLD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1142 ; TAILFOLD-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
1143 ; TAILFOLD: loop.body:
1144 ; TAILFOLD-NEXT: [[TMP0:%.*]] = load float, ptr [[GEP]], align 4
1145 ; TAILFOLD-NEXT: [[PRED:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00
1146 ; TAILFOLD-NEXT: br i1 [[PRED]], label [[LOOP_LATCH]], label [[THEN:%.*]]
1148 ; TAILFOLD-NEXT: store float 1.000000e+01, ptr [[GEP]], align 4
1149 ; TAILFOLD-NEXT: br label [[LOOP_LATCH]]
1150 ; TAILFOLD: loop.latch:
1151 ; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1152 ; TAILFOLD-NEXT: br label [[LOOP_HEADER]]
1154 ; TAILFOLD-NEXT: ret void
1157 br label %loop.header
1160 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1161 %gep = getelementptr float, ptr %addr, i64 %iv
1162 %exitcond.not = icmp eq i64 %iv, 200
1163 br i1 %exitcond.not, label %exit, label %loop.body
1166 %0 = load float, ptr %gep, align 4
1167 %pred = fcmp oeq float %0, 0.0
1168 br i1 %pred, label %loop.latch, label %then
1171 store float 10.0, ptr %gep, align 4
1172 br label %loop.latch
1175 %iv.next = add nuw nsw i64 %iv, 1
1176 br label %loop.header
1182 define i32 @me_reduction(ptr %addr) {
1183 ; CHECK-LABEL: @me_reduction(
1184 ; CHECK-NEXT: entry:
1185 ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
1187 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
1188 ; CHECK: vector.body:
1189 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
1190 ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[VECTOR_BODY]] ]
1191 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
1192 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ADDR:%.*]], i64 [[TMP0]]
1193 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], i32 0
1194 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1195 ; CHECK-NEXT: [[TMP3]] = add <2 x i32> [[VEC_PHI]], [[WIDE_LOAD]]
1196 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1197 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 200
1198 ; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]]
1199 ; CHECK: middle.block:
1200 ; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[TMP3]])
1201 ; CHECK-NEXT: br label [[SCALAR_PH]]
1203 ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 200, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
1204 ; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP5]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ]
1205 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
1206 ; CHECK: loop.header:
1207 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1208 ; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ]
1209 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[ADDR]], i64 [[IV]]
1210 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1211 ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
1212 ; CHECK: loop.latch:
1213 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[GEP]], align 4
1214 ; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP6]]
1215 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1216 ; CHECK-NEXT: [[EXITCOND2_NOT:%.*]] = icmp eq i64 [[IV]], 400
1217 ; CHECK-NEXT: br i1 [[EXITCOND2_NOT]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP23:![0-9]+]]
1219 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ 0, [[LOOP_HEADER]] ], [ [[ACCUM_NEXT]], [[LOOP_LATCH]] ]
1220 ; CHECK-NEXT: ret i32 [[LCSSA]]
1222 ; TAILFOLD-LABEL: @me_reduction(
1223 ; TAILFOLD-NEXT: entry:
1224 ; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]]
1225 ; TAILFOLD: loop.header:
1226 ; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1227 ; TAILFOLD-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ]
1228 ; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[ADDR:%.*]], i64 [[IV]]
1229 ; TAILFOLD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1230 ; TAILFOLD-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
1231 ; TAILFOLD: loop.latch:
1232 ; TAILFOLD-NEXT: [[TMP0:%.*]] = load i32, ptr [[GEP]], align 4
1233 ; TAILFOLD-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]]
1234 ; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1235 ; TAILFOLD-NEXT: [[EXITCOND2_NOT:%.*]] = icmp eq i64 [[IV]], 400
1236 ; TAILFOLD-NEXT: br i1 [[EXITCOND2_NOT]], label [[EXIT]], label [[LOOP_HEADER]]
1238 ; TAILFOLD-NEXT: [[LCSSA:%.*]] = phi i32 [ 0, [[LOOP_HEADER]] ], [ [[ACCUM_NEXT]], [[LOOP_LATCH]] ]
1239 ; TAILFOLD-NEXT: ret i32 [[LCSSA]]
1242 br label %loop.header
1245 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1246 %accum = phi i32 [0, %entry], [%accum.next, %loop.latch]
1247 %gep = getelementptr i32, ptr %addr, i64 %iv
1248 %exitcond.not = icmp eq i64 %iv, 200
1249 br i1 %exitcond.not, label %exit, label %loop.latch
1252 %0 = load i32, ptr %gep, align 4
1253 %accum.next = add i32 %accum, %0
1254 %iv.next = add nuw nsw i64 %iv, 1
1255 %exitcond2.not = icmp eq i64 %iv, 400
1256 br i1 %exitcond2.not, label %exit, label %loop.header
1259 %lcssa = phi i32 [0, %loop.header], [%accum.next, %loop.latch]
1263 ; TODO: The current definition of reduction is too strict, we can vectorize
1264 ; this. There's an analogous single exit case where we extract the N-1
1265 ; value of the reduction that we can also handle. If we fix the later, the
1266 ; multiple exit case probably falls out.
1267 define i32 @me_reduction2(ptr %addr) {
1268 ; CHECK-LABEL: @me_reduction2(
1269 ; CHECK-NEXT: entry:
1270 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
1271 ; CHECK: loop.header:
1272 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1273 ; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ]
1274 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[ADDR:%.*]], i64 [[IV]]
1275 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1276 ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
1277 ; CHECK: loop.latch:
1278 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[GEP]], align 4
1279 ; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]]
1280 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1281 ; CHECK-NEXT: br label [[LOOP_HEADER]]
1283 ; CHECK-NEXT: [[ACCUM_LCSSA:%.*]] = phi i32 [ [[ACCUM]], [[LOOP_HEADER]] ]
1284 ; CHECK-NEXT: ret i32 [[ACCUM_LCSSA]]
1286 ; TAILFOLD-LABEL: @me_reduction2(
1287 ; TAILFOLD-NEXT: entry:
1288 ; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]]
1289 ; TAILFOLD: loop.header:
1290 ; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1291 ; TAILFOLD-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ]
1292 ; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[ADDR:%.*]], i64 [[IV]]
1293 ; TAILFOLD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200
1294 ; TAILFOLD-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
1295 ; TAILFOLD: loop.latch:
1296 ; TAILFOLD-NEXT: [[TMP0:%.*]] = load i32, ptr [[GEP]], align 4
1297 ; TAILFOLD-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]]
1298 ; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1299 ; TAILFOLD-NEXT: br label [[LOOP_HEADER]]
1301 ; TAILFOLD-NEXT: [[ACCUM_LCSSA:%.*]] = phi i32 [ [[ACCUM]], [[LOOP_HEADER]] ]
1302 ; TAILFOLD-NEXT: ret i32 [[ACCUM_LCSSA]]
1305 br label %loop.header
1308 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1309 %accum = phi i32 [0, %entry], [%accum.next, %loop.latch]
1310 %gep = getelementptr i32, ptr %addr, i64 %iv
1311 %exitcond.not = icmp eq i64 %iv, 200
1312 br i1 %exitcond.not, label %exit, label %loop.latch
1315 %0 = load i32, ptr %gep, align 4
1316 %accum.next = add i32 %accum, %0
1317 %iv.next = add nuw nsw i64 %iv, 1
1318 br label %loop.header