1 ; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s
3 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
5 ;CHECK-LABEL: @reduction_sum(
9 ;CHECK: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
11 define i32 @reduction_sum(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
12 %1 = icmp sgt i32 %n, 0
13 br i1 %1, label %.lr.ph, label %._crit_edge
15 .lr.ph: ; preds = %0, %.lr.ph
16 %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
17 %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ]
18 %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
19 %3 = load i32, i32* %2, align 4
20 %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
21 %5 = load i32, i32* %4, align 4
22 %6 = trunc i64 %indvars.iv to i32
23 %7 = add i32 %sum.02, %6
26 %indvars.iv.next = add i64 %indvars.iv, 1
27 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
28 %exitcond = icmp eq i32 %lftr.wideiv, %n
29 br i1 %exitcond, label %._crit_edge, label %.lr.ph
31 ._crit_edge: ; preds = %.lr.ph, %0
32 %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
36 ;CHECK-LABEL: @reduction_prod(
38 ;CHECK: load <4 x i32>
40 ;CHECK: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32>
42 define i32 @reduction_prod(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
43 %1 = icmp sgt i32 %n, 0
44 br i1 %1, label %.lr.ph, label %._crit_edge
46 .lr.ph: ; preds = %0, %.lr.ph
47 %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
48 %prod.02 = phi i32 [ %9, %.lr.ph ], [ 1, %0 ]
49 %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
50 %3 = load i32, i32* %2, align 4
51 %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
52 %5 = load i32, i32* %4, align 4
53 %6 = trunc i64 %indvars.iv to i32
54 %7 = mul i32 %prod.02, %6
57 %indvars.iv.next = add i64 %indvars.iv, 1
58 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
59 %exitcond = icmp eq i32 %lftr.wideiv, %n
60 br i1 %exitcond, label %._crit_edge, label %.lr.ph
62 ._crit_edge: ; preds = %.lr.ph, %0
63 %prod.0.lcssa = phi i32 [ 1, %0 ], [ %9, %.lr.ph ]
67 ;CHECK-LABEL: @reduction_mix(
69 ;CHECK: load <4 x i32>
70 ;CHECK: mul nsw <4 x i32>
71 ;CHECK: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
73 define i32 @reduction_mix(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
74 %1 = icmp sgt i32 %n, 0
75 br i1 %1, label %.lr.ph, label %._crit_edge
77 .lr.ph: ; preds = %0, %.lr.ph
78 %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
79 %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ]
80 %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
81 %3 = load i32, i32* %2, align 4
82 %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
83 %5 = load i32, i32* %4, align 4
84 %6 = mul nsw i32 %5, %3
85 %7 = trunc i64 %indvars.iv to i32
86 %8 = add i32 %sum.02, %7
88 %indvars.iv.next = add i64 %indvars.iv, 1
89 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
90 %exitcond = icmp eq i32 %lftr.wideiv, %n
91 br i1 %exitcond, label %._crit_edge, label %.lr.ph
93 ._crit_edge: ; preds = %.lr.ph, %0
94 %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
98 ;CHECK-LABEL: @reduction_mul(
100 ;CHECK: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32>
102 define i32 @reduction_mul(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
103 %1 = icmp sgt i32 %n, 0
104 br i1 %1, label %.lr.ph, label %._crit_edge
106 .lr.ph: ; preds = %0, %.lr.ph
107 %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
108 %sum.02 = phi i32 [ %9, %.lr.ph ], [ 19, %0 ]
109 %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
110 %3 = load i32, i32* %2, align 4
111 %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
112 %5 = load i32, i32* %4, align 4
113 %6 = trunc i64 %indvars.iv to i32
116 %9 = mul i32 %8, %sum.02
117 %indvars.iv.next = add i64 %indvars.iv, 1
118 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
119 %exitcond = icmp eq i32 %lftr.wideiv, %n
120 br i1 %exitcond, label %._crit_edge, label %.lr.ph
122 ._crit_edge: ; preds = %.lr.ph, %0
123 %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
127 ;CHECK-LABEL: @start_at_non_zero(
128 ;CHECK: phi <4 x i32>
129 ;CHECK: <i32 120, i32 0, i32 0, i32 0>
130 ;CHECK: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
132 define i32 @start_at_non_zero(i32* nocapture %in, i32* nocapture %coeff, i32* nocapture %out, i32 %n) nounwind uwtable readonly ssp {
134 %cmp7 = icmp sgt i32 %n, 0
135 br i1 %cmp7, label %for.body, label %for.end
137 for.body: ; preds = %entry, %for.body
138 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
139 %sum.09 = phi i32 [ %add, %for.body ], [ 120, %entry ]
140 %arrayidx = getelementptr inbounds i32, i32* %in, i64 %indvars.iv
141 %0 = load i32, i32* %arrayidx, align 4
142 %arrayidx2 = getelementptr inbounds i32, i32* %coeff, i64 %indvars.iv
143 %1 = load i32, i32* %arrayidx2, align 4
144 %mul = mul nsw i32 %1, %0
145 %add = add nsw i32 %mul, %sum.09
146 %indvars.iv.next = add i64 %indvars.iv, 1
147 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
148 %exitcond = icmp eq i32 %lftr.wideiv, %n
149 br i1 %exitcond, label %for.end, label %for.body
151 for.end: ; preds = %for.body, %entry
152 %sum.0.lcssa = phi i32 [ 120, %entry ], [ %add, %for.body ]
156 ;CHECK-LABEL: @reduction_and(
157 ;CHECK: <i32 -1, i32 -1, i32 -1, i32 -1>
158 ;CHECK: and <4 x i32>
159 ;CHECK: call i32 @llvm.vector.reduce.and.v4i32(<4 x i32>
161 define i32 @reduction_and(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
163 %cmp7 = icmp sgt i32 %n, 0
164 br i1 %cmp7, label %for.body, label %for.end
166 for.body: ; preds = %entry, %for.body
167 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
168 %result.08 = phi i32 [ %and, %for.body ], [ -1, %entry ]
169 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
170 %0 = load i32, i32* %arrayidx, align 4
171 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
172 %1 = load i32, i32* %arrayidx2, align 4
173 %add = add nsw i32 %1, %0
174 %and = and i32 %add, %result.08
175 %indvars.iv.next = add i64 %indvars.iv, 1
176 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
177 %exitcond = icmp eq i32 %lftr.wideiv, %n
178 br i1 %exitcond, label %for.end, label %for.body
180 for.end: ; preds = %for.body, %entry
181 %result.0.lcssa = phi i32 [ -1, %entry ], [ %and, %for.body ]
182 ret i32 %result.0.lcssa
185 ;CHECK-LABEL: @reduction_or(
187 ;CHECK: call i32 @llvm.vector.reduce.or.v4i32(<4 x i32>
189 define i32 @reduction_or(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
191 %cmp7 = icmp sgt i32 %n, 0
192 br i1 %cmp7, label %for.body, label %for.end
194 for.body: ; preds = %entry, %for.body
195 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
196 %result.08 = phi i32 [ %or, %for.body ], [ 0, %entry ]
197 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
198 %0 = load i32, i32* %arrayidx, align 4
199 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
200 %1 = load i32, i32* %arrayidx2, align 4
201 %add = add nsw i32 %1, %0
202 %or = or i32 %add, %result.08
203 %indvars.iv.next = add i64 %indvars.iv, 1
204 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
205 %exitcond = icmp eq i32 %lftr.wideiv, %n
206 br i1 %exitcond, label %for.end, label %for.body
208 for.end: ; preds = %for.body, %entry
209 %result.0.lcssa = phi i32 [ 0, %entry ], [ %or, %for.body ]
210 ret i32 %result.0.lcssa
213 ;CHECK-LABEL: @reduction_xor(
214 ;CHECK: xor <4 x i32>
215 ;CHECK: call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32>
217 define i32 @reduction_xor(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
219 %cmp7 = icmp sgt i32 %n, 0
220 br i1 %cmp7, label %for.body, label %for.end
222 for.body: ; preds = %entry, %for.body
223 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
224 %result.08 = phi i32 [ %xor, %for.body ], [ 0, %entry ]
225 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
226 %0 = load i32, i32* %arrayidx, align 4
227 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
228 %1 = load i32, i32* %arrayidx2, align 4
229 %add = add nsw i32 %1, %0
230 %xor = xor i32 %add, %result.08
231 %indvars.iv.next = add i64 %indvars.iv, 1
232 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
233 %exitcond = icmp eq i32 %lftr.wideiv, %n
234 br i1 %exitcond, label %for.end, label %for.body
236 for.end: ; preds = %for.body, %entry
237 %result.0.lcssa = phi i32 [ 0, %entry ], [ %xor, %for.body ]
238 ret i32 %result.0.lcssa
241 ; In this code the subtracted variable is on the RHS and this is not an induction variable.
242 ;CHECK-LABEL: @reduction_sub_rhs(
243 ;CHECK-NOT: phi <4 x i32>
244 ;CHECK-NOT: sub nsw <4 x i32>
246 define i32 @reduction_sub_rhs(i32 %n, i32* noalias nocapture %A) nounwind uwtable readonly {
248 %cmp4 = icmp sgt i32 %n, 0
249 br i1 %cmp4, label %for.body, label %for.end
251 for.body: ; preds = %entry, %for.body
252 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
253 %x.05 = phi i32 [ %sub, %for.body ], [ 0, %entry ]
254 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
255 %0 = load i32, i32* %arrayidx, align 4
256 %sub = sub nsw i32 %0, %x.05
257 %indvars.iv.next = add i64 %indvars.iv, 1
258 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
259 %exitcond = icmp eq i32 %lftr.wideiv, %n
260 br i1 %exitcond, label %for.end, label %for.body
262 for.end: ; preds = %for.body, %entry
263 %x.0.lcssa = phi i32 [ 0, %entry ], [ %sub, %for.body ]
268 ; In this test the reduction variable is on the LHS and we can vectorize it.
269 ;CHECK-LABEL: @reduction_sub_lhs(
270 ;CHECK: phi <4 x i32>
271 ;CHECK: sub <4 x i32>
273 define i32 @reduction_sub_lhs(i32 %n, i32* noalias nocapture %A) nounwind uwtable readonly {
275 %cmp4 = icmp sgt i32 %n, 0
276 br i1 %cmp4, label %for.body, label %for.end
278 for.body: ; preds = %entry, %for.body
279 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
280 %x.05 = phi i32 [ %sub, %for.body ], [ 0, %entry ]
281 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
282 %0 = load i32, i32* %arrayidx, align 4
283 %sub = sub nsw i32 %x.05, %0
284 %indvars.iv.next = add i64 %indvars.iv, 1
285 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
286 %exitcond = icmp eq i32 %lftr.wideiv, %n
287 br i1 %exitcond, label %for.end, label %for.body
289 for.end: ; preds = %for.body, %entry
290 %x.0.lcssa = phi i32 [ 0, %entry ], [ %sub, %for.body ]
294 ; We can vectorize conditional reductions with multi-input phis.
295 ; CHECK: reduction_conditional
296 ; CHECK: fadd fast <4 x float>
298 define float @reduction_conditional(float* %A, float* %B, float* %C, float %S) {
303 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
304 %sum.033 = phi float [ %S, %entry ], [ %sum.1, %for.inc ]
305 %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv
306 %0 = load float, float* %arrayidx, align 4
307 %arrayidx2 = getelementptr inbounds float, float* %B, i64 %indvars.iv
308 %1 = load float, float* %arrayidx2, align 4
309 %cmp3 = fcmp ogt float %0, %1
310 br i1 %cmp3, label %if.then, label %for.inc
313 %cmp6 = fcmp ogt float %1, 1.000000e+00
314 br i1 %cmp6, label %if.then8, label %if.else
317 %add = fadd fast float %sum.033, %0
321 %cmp14 = fcmp ogt float %0, 2.000000e+00
322 br i1 %cmp14, label %if.then16, label %for.inc
325 %add19 = fadd fast float %sum.033, %1
329 %sum.1 = phi float [ %add, %if.then8 ], [ %add19, %if.then16 ], [ %sum.033, %if.else ], [ %sum.033, %for.body ]
330 %indvars.iv.next = add i64 %indvars.iv, 1
331 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
332 %exitcond = icmp ne i32 %lftr.wideiv, 128
333 br i1 %exitcond, label %for.body, label %for.end
336 %sum.1.lcssa = phi float [ %sum.1, %for.inc ]
337 ret float %sum.1.lcssa
340 ; We can't vectorize reductions with phi inputs from outside the reduction.
341 ; CHECK: noreduction_phi
342 ; CHECK-NOT: fadd <4 x float>
343 define float @noreduction_phi(float* %A, float* %B, float* %C, float %S) {
348 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
349 %sum.033 = phi float [ %S, %entry ], [ %sum.1, %for.inc ]
350 %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv
351 %0 = load float, float* %arrayidx, align 4
352 %arrayidx2 = getelementptr inbounds float, float* %B, i64 %indvars.iv
353 %1 = load float, float* %arrayidx2, align 4
354 %cmp3 = fcmp ogt float %0, %1
355 br i1 %cmp3, label %if.then, label %for.inc
358 %cmp6 = fcmp ogt float %1, 1.000000e+00
359 br i1 %cmp6, label %if.then8, label %if.else
362 %add = fadd fast float %sum.033, %0
366 %cmp14 = fcmp ogt float %0, 2.000000e+00
367 br i1 %cmp14, label %if.then16, label %for.inc
370 %add19 = fadd fast float %sum.033, %1
374 %sum.1 = phi float [ %add, %if.then8 ], [ %add19, %if.then16 ], [ 0.000000e+00, %if.else ], [ %sum.033, %for.body ]
375 %indvars.iv.next = add i64 %indvars.iv, 1
376 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
377 %exitcond = icmp ne i32 %lftr.wideiv, 128
378 br i1 %exitcond, label %for.body, label %for.end
381 %sum.1.lcssa = phi float [ %sum.1, %for.inc ]
382 ret float %sum.1.lcssa
385 ; We can't vectorize reductions that feed another header PHI.
386 ; CHECK: noredux_header_phi
387 ; CHECK-NOT: fadd <4 x float>
389 define float @noredux_header_phi(float* %A, float* %B, float* %C, float %S) {
394 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
395 %sum2.09 = phi float [ 0.000000e+00, %entry ], [ %add1, %for.body ]
396 %sum.08 = phi float [ %S, %entry ], [ %add, %for.body ]
397 %arrayidx = getelementptr inbounds float, float* %B, i64 %indvars.iv
398 %0 = load float, float* %arrayidx, align 4
399 %add = fadd fast float %sum.08, %0
400 %add1 = fadd fast float %sum2.09, %add
401 %indvars.iv.next = add i64 %indvars.iv, 1
402 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
403 %exitcond = icmp ne i32 %lftr.wideiv, 128
404 br i1 %exitcond, label %for.body, label %for.end
407 %add1.lcssa = phi float [ %add1, %for.body ]
408 %add.lcssa = phi float [ %add, %for.body ]
409 %add2 = fadd fast float %add.lcssa, %add1.lcssa
414 ; When vectorizing a reduction whose loop header phi value is used outside the
415 ; loop special care must be taken. Otherwise, the reduced value feeding into the
416 ; outside user misses a few iterations (VF-1) of the loop.
419 ; CHECK-LABEL: @phivalueredux(
422 define i32 @phivalueredux(i32 %p) {
427 %t.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
428 %p.addr.02 = phi i32 [ %p, %entry ], [ %xor, %for.body ]
429 %xor = xor i32 %p.addr.02, -1
430 %inc = add nsw i32 %t.03, 1
431 %exitcond = icmp eq i32 %inc, 16
432 br i1 %exitcond, label %for.end, label %for.body
438 ; Don't vectorize a reduction value that is not the last in a reduction cyle. We
439 ; would loose iterations (VF-1) on the operations after that use.
442 ; CHECK-LABEL: not_last_operation
444 define i32 @not_last_operation(i32 %p, i32 %val) {
446 %tobool = icmp eq i32 %p, 0
450 %inc613.1 = phi i32 [ 0, %entry ], [ %inc6.1, %for.body ]
451 %inc511.1 = phi i32 [ %val, %entry ], [ %inc5.1, %for.body ]
452 %0 = zext i1 %tobool to i32
453 %inc4.1 = xor i32 %0, 1
454 %inc511.1.inc4.1 = add nsw i32 %inc511.1, %inc4.1
455 %inc5.1 = add nsw i32 %inc511.1.inc4.1, 1
456 %inc6.1 = add nsw i32 %inc613.1, 1
457 %exitcond.1 = icmp eq i32 %inc6.1, 22
458 br i1 %exitcond.1, label %exit, label %for.body
461 %inc.2 = add nsw i32 %inc511.1.inc4.1, 2
465 ;CHECK-LABEL: @reduction_sum_multiuse(
466 ;CHECK: phi <4 x i32>
467 ;CHECK: load <4 x i32>
468 ;CHECK: add <4 x i32>
469 ;CHECK: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
470 ;CHECK: %sum.copy = phi i32 [ %[[SCALAR:.*]], %.lr.ph ], [ %[[VECTOR:.*]], %middle.block ]
472 define i32 @reduction_sum_multiuse(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) {
473 %1 = icmp sgt i32 %n, 0
474 br i1 %1, label %.lr.ph.preheader, label %end
475 .lr.ph.preheader: ; preds = %0
478 .lr.ph: ; preds = %0, %.lr.ph
479 %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %.lr.ph.preheader ]
480 %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %.lr.ph.preheader ]
481 %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
482 %3 = load i32, i32* %2, align 4
483 %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
484 %5 = load i32, i32* %4, align 4
485 %6 = trunc i64 %indvars.iv to i32
486 %7 = add i32 %sum.02, %6
489 %indvars.iv.next = add i64 %indvars.iv, 1
490 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
491 %exitcond = icmp eq i32 %lftr.wideiv, %n
492 br i1 %exitcond, label %._crit_edge, label %.lr.ph
494 ._crit_edge: ; preds = %.lr.ph, %0
495 %sum.lcssa = phi i32 [ %9, %.lr.ph ]
496 %sum.copy = phi i32 [ %9, %.lr.ph ]
500 %f1 = phi i32 [ 0, %0 ], [ %sum.lcssa, %._crit_edge ]
501 %f2 = phi i32 [ 0, %0 ], [ %sum.copy, %._crit_edge ]
502 %final = add i32 %f1, %f2
506 ; This looks like a predicated reduction, but it is a reset of the reduction
507 ; variable. We cannot vectorize this.
508 ; CHECK-LABEL: reduction_reset(
509 ; CHECK-NOT: <4 x i32>
510 define void @reduction_reset(i32 %N, i32* nocapture readonly %arrayA, i32* nocapture %arrayB) {
512 %c4 = icmp sgt i32 %N, 0
513 br i1 %c4, label %.lr.ph.preheader, label %._crit_edge
515 .lr.ph.preheader: ; preds = %entry
517 %wide.trip.count = zext i32 %N to i64
520 .lr.ph: ; preds = %.lr.ph, %.lr.ph.preheader
521 %indvars.iv = phi i64 [ 0, %.lr.ph.preheader ], [ %indvars.iv.next, %.lr.ph ]
522 %.017 = phi i32 [ 100, %.lr.ph.preheader ], [ %csel, %.lr.ph ]
523 %c6 = getelementptr inbounds i32, i32* %arrayA, i64 %indvars.iv
524 %c7 = load i32, i32* %c6, align 4
525 %c8 = icmp sgt i32 %c7, 0
526 %c9 = add nsw i32 %c7, %.017
527 %csel = select i1 %c8, i32 %c9, i32 0
528 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
529 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
530 br i1 %exitcond, label %._crit_edge.loopexit, label %.lr.ph
532 ._crit_edge.loopexit: ; preds = %.lr.ph
533 %csel.lcssa = phi i32 [ %csel, %.lr.ph ]
534 %phitmp19 = sext i32 %c5 to i64
535 br label %._crit_edge
537 ._crit_edge: ; preds = %._crit_edge.loopexit, %entry
538 %.015.lcssa = phi i64 [ -1, %entry ], [ %phitmp19, %._crit_edge.loopexit ]
539 %.0.lcssa = phi i32 [ 100, %entry ], [ %csel.lcssa, %._crit_edge.loopexit ]
540 %c10 = getelementptr inbounds i32, i32* %arrayB, i64 %.015.lcssa
541 store i32 %.0.lcssa, i32* %c10, align 4
545 ; Can vectorize reduction with redundant single-operand phi input.
546 define i64 @reduction_with_phi_with_one_incoming_on_backedge(i16 %n, i64* %A) {
547 ; CHECK-LABEL: @reduction_with_phi_with_one_incoming_on_backedge
548 ; CHECK: add <4 x i64>
551 br label %loop.header
554 %iv = phi i16 [ 1, %entry ], [ %iv.next, %loop.latch ]
555 %sum = phi i64 [ 0, %entry ], [ %phi.sum.next, %loop.latch ]
556 %gep.A = getelementptr i64, i64* %A, i16 %iv
557 %lv.A = load i64, i64* %gep.A
558 %sum.next = add nsw i64 %sum, %lv.A
562 %phi.sum.next = phi i64 [ %sum.next, %loop.header ]
566 %iv.next = add nsw i16 %iv, 1
567 %cond = icmp slt i16 %iv.next, %n
568 br i1 %cond, label %loop.header, label %exit
571 %lcssa.exit = phi i64 [ %phi.sum.next, %loop.latch ]
575 ; Can vectorize reduction with redundant two-operand phi input.
576 define i64 @reduction_with_phi_with_two_incoming_on_backedge(i16 %n, i64* %A) {
577 ; CHECK-LABEL: @reduction_with_phi_with_two_incoming_on_backedge
578 ; CHECK: add <4 x i64>
581 br label %loop.header
584 %iv = phi i16 [ 1, %entry ], [ %iv.next, %loop.latch ]
585 %sum = phi i64 [ 0, %entry ], [ %phi.sum.next, %loop.latch ]
586 %gep.A = getelementptr i64, i64* %A, i16 %iv
587 %lv.A = load i64, i64* %gep.A
588 %sum.next = add nsw i64 %sum, %lv.A
589 %cmp.0 = icmp eq i64 %lv.A, 29
590 br i1 %cmp.0, label %loop.bb, label %loop.latch
596 %phi.sum.next = phi i64 [ %sum.next, %loop.bb ], [ %sum.next, %loop.header ]
597 %iv.next = add nsw i16 %iv, 1
598 %cond = icmp slt i16 %iv.next, %n
599 br i1 %cond, label %loop.header, label %exit
602 %lcssa.exit = phi i64 [ %phi.sum.next, %loop.latch ]
606 ; Make sure any check-not directives are not triggered by function declarations.