1 ; RUN: opt -slp-vectorizer -slp-vectorize-hor -S < %s -mtriple=x86_64-apple-macosx -mcpu=corei7-avx | 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"
7 ; int foo(float *A, int n) {
9 ; for (intptr_t i=0; i < n; ++i) {
18 ; CHECK-LABEL: add_red
19 ; CHECK: fmul <4 x float>
20 ; CHECK: shufflevector <4 x float>
22 define i32 @add_red(float* %A, i32 %n) {
24 %cmp31 = icmp sgt i32 %n, 0
25 br i1 %cmp31, label %for.body.lr.ph, label %for.end
28 %0 = sext i32 %n to i64
32 %i.033 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
33 %sum.032 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add17, %for.body ]
34 %mul = shl nsw i64 %i.033, 2
35 %arrayidx = getelementptr inbounds float* %A, i64 %mul
36 %1 = load float* %arrayidx, align 4
37 %mul2 = fmul float %1, 7.000000e+00
38 %add28 = or i64 %mul, 1
39 %arrayidx4 = getelementptr inbounds float* %A, i64 %add28
40 %2 = load float* %arrayidx4, align 4
41 %mul5 = fmul float %2, 7.000000e+00
42 %add6 = fadd fast float %mul2, %mul5
43 %add829 = or i64 %mul, 2
44 %arrayidx9 = getelementptr inbounds float* %A, i64 %add829
45 %3 = load float* %arrayidx9, align 4
46 %mul10 = fmul float %3, 7.000000e+00
47 %add11 = fadd fast float %add6, %mul10
48 %add1330 = or i64 %mul, 3
49 %arrayidx14 = getelementptr inbounds float* %A, i64 %add1330
50 %4 = load float* %arrayidx14, align 4
51 %mul15 = fmul float %4, 7.000000e+00
52 %add16 = fadd fast float %add11, %mul15
53 %add17 = fadd fast float %sum.032, %add16
54 %inc = add nsw i64 %i.033, 1
55 %exitcond = icmp eq i64 %inc, %0
56 br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body
58 for.cond.for.end_crit_edge:
59 %phitmp = fptosi float %add17 to i32
63 %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
67 ; int foo(float * restrict A, float * restrict B, int n) {
69 ; for (intptr_t i=0; i < n; ++i) {
70 ; sum *= B[0]*A[i*4 ] +
78 ; CHECK-LABEL: mul_red
79 ; CHECK: fmul <4 x float>
80 ; CHECK: shufflevector <4 x float>
82 define i32 @mul_red(float* noalias %A, float* noalias %B, i32 %n) {
84 %cmp38 = icmp sgt i32 %n, 0
85 br i1 %cmp38, label %for.body.lr.ph, label %for.end
88 %0 = load float* %B, align 4
89 %arrayidx4 = getelementptr inbounds float* %B, i64 1
90 %1 = load float* %arrayidx4, align 4
91 %arrayidx9 = getelementptr inbounds float* %B, i64 2
92 %2 = load float* %arrayidx9, align 4
93 %arrayidx15 = getelementptr inbounds float* %B, i64 3
94 %3 = load float* %arrayidx15, align 4
95 %4 = sext i32 %n to i64
99 %i.040 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
100 %sum.039 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %mul21, %for.body ]
101 %mul = shl nsw i64 %i.040, 2
102 %arrayidx2 = getelementptr inbounds float* %A, i64 %mul
103 %5 = load float* %arrayidx2, align 4
104 %mul3 = fmul float %0, %5
105 %add35 = or i64 %mul, 1
106 %arrayidx6 = getelementptr inbounds float* %A, i64 %add35
107 %6 = load float* %arrayidx6, align 4
108 %mul7 = fmul float %1, %6
109 %add8 = fadd fast float %mul3, %mul7
110 %add1136 = or i64 %mul, 2
111 %arrayidx12 = getelementptr inbounds float* %A, i64 %add1136
112 %7 = load float* %arrayidx12, align 4
113 %mul13 = fmul float %2, %7
114 %add14 = fadd fast float %add8, %mul13
115 %add1737 = or i64 %mul, 3
116 %arrayidx18 = getelementptr inbounds float* %A, i64 %add1737
117 %8 = load float* %arrayidx18, align 4
118 %mul19 = fmul float %3, %8
119 %add20 = fadd fast float %add14, %mul19
120 %mul21 = fmul float %sum.039, %add20
121 %inc = add nsw i64 %i.040, 1
122 %exitcond = icmp eq i64 %inc, %4
123 br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body
125 for.cond.for.end_crit_edge:
126 %phitmp = fptosi float %mul21 to i32
130 %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
134 ; int foo(float * restrict A, float * restrict B, int n) {
136 ; for (intptr_t i=0; i < n; ++i) {
137 ; sum += B[0]*A[i*6 ] +
150 ; CHECK-LABEL: long_red
151 ; CHECK: fmul <4 x float>
152 ; CHECK: shufflevector <4 x float>
154 define i32 @long_red(float* noalias %A, float* noalias %B, i32 %n) {
156 %cmp81 = icmp sgt i32 %n, 0
157 br i1 %cmp81, label %for.body.lr.ph, label %for.end
160 %0 = load float* %B, align 4
161 %arrayidx4 = getelementptr inbounds float* %B, i64 1
162 %1 = load float* %arrayidx4, align 4
163 %arrayidx9 = getelementptr inbounds float* %B, i64 2
164 %2 = load float* %arrayidx9, align 4
165 %arrayidx15 = getelementptr inbounds float* %B, i64 3
166 %3 = load float* %arrayidx15, align 4
167 %arrayidx21 = getelementptr inbounds float* %B, i64 4
168 %4 = load float* %arrayidx21, align 4
169 %arrayidx27 = getelementptr inbounds float* %B, i64 5
170 %5 = load float* %arrayidx27, align 4
171 %arrayidx33 = getelementptr inbounds float* %B, i64 6
172 %6 = load float* %arrayidx33, align 4
173 %arrayidx39 = getelementptr inbounds float* %B, i64 7
174 %7 = load float* %arrayidx39, align 4
175 %arrayidx45 = getelementptr inbounds float* %B, i64 8
176 %8 = load float* %arrayidx45, align 4
177 %9 = sext i32 %n to i64
181 %i.083 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
182 %sum.082 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add51, %for.body ]
183 %mul = mul nsw i64 %i.083, 6
184 %arrayidx2 = getelementptr inbounds float* %A, i64 %mul
185 %10 = load float* %arrayidx2, align 4
186 %mul3 = fmul fast float %0, %10
187 %add80 = or i64 %mul, 1
188 %arrayidx6 = getelementptr inbounds float* %A, i64 %add80
189 %11 = load float* %arrayidx6, align 4
190 %mul7 = fmul fast float %1, %11
191 %add8 = fadd fast float %mul3, %mul7
192 %add11 = add nsw i64 %mul, 2
193 %arrayidx12 = getelementptr inbounds float* %A, i64 %add11
194 %12 = load float* %arrayidx12, align 4
195 %mul13 = fmul fast float %2, %12
196 %add14 = fadd fast float %add8, %mul13
197 %add17 = add nsw i64 %mul, 3
198 %arrayidx18 = getelementptr inbounds float* %A, i64 %add17
199 %13 = load float* %arrayidx18, align 4
200 %mul19 = fmul fast float %3, %13
201 %add20 = fadd fast float %add14, %mul19
202 %add23 = add nsw i64 %mul, 4
203 %arrayidx24 = getelementptr inbounds float* %A, i64 %add23
204 %14 = load float* %arrayidx24, align 4
205 %mul25 = fmul fast float %4, %14
206 %add26 = fadd fast float %add20, %mul25
207 %add29 = add nsw i64 %mul, 5
208 %arrayidx30 = getelementptr inbounds float* %A, i64 %add29
209 %15 = load float* %arrayidx30, align 4
210 %mul31 = fmul fast float %5, %15
211 %add32 = fadd fast float %add26, %mul31
212 %add35 = add nsw i64 %mul, 6
213 %arrayidx36 = getelementptr inbounds float* %A, i64 %add35
214 %16 = load float* %arrayidx36, align 4
215 %mul37 = fmul fast float %6, %16
216 %add38 = fadd fast float %add32, %mul37
217 %add41 = add nsw i64 %mul, 7
218 %arrayidx42 = getelementptr inbounds float* %A, i64 %add41
219 %17 = load float* %arrayidx42, align 4
220 %mul43 = fmul fast float %7, %17
221 %add44 = fadd fast float %add38, %mul43
222 %add47 = add nsw i64 %mul, 8
223 %arrayidx48 = getelementptr inbounds float* %A, i64 %add47
224 %18 = load float* %arrayidx48, align 4
225 %mul49 = fmul fast float %8, %18
226 %add50 = fadd fast float %add44, %mul49
227 %add51 = fadd fast float %sum.082, %add50
228 %inc = add nsw i64 %i.083, 1
229 %exitcond = icmp eq i64 %inc, %9
230 br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body
232 for.cond.for.end_crit_edge:
233 %phitmp = fptosi float %add51 to i32
237 %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
241 ; int foo(float * restrict A, float * restrict B, int n) {
243 ; for (intptr_t i=0; i < n; ++i) {
244 ; sum += B[0]*A[i*4 ];
245 ; sum += B[1]*A[i*4+1];
246 ; sum += B[2]*A[i*4+2];
247 ; sum += B[3]*A[i*4+3];
252 ; CHECK-LABEL: chain_red
253 ; CHECK: fmul <4 x float>
254 ; CHECK: shufflevector <4 x float>
256 define i32 @chain_red(float* noalias %A, float* noalias %B, i32 %n) {
258 %cmp41 = icmp sgt i32 %n, 0
259 br i1 %cmp41, label %for.body.lr.ph, label %for.end
262 %0 = load float* %B, align 4
263 %arrayidx4 = getelementptr inbounds float* %B, i64 1
264 %1 = load float* %arrayidx4, align 4
265 %arrayidx10 = getelementptr inbounds float* %B, i64 2
266 %2 = load float* %arrayidx10, align 4
267 %arrayidx16 = getelementptr inbounds float* %B, i64 3
268 %3 = load float* %arrayidx16, align 4
269 %4 = sext i32 %n to i64
273 %i.043 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
274 %sum.042 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add21, %for.body ]
275 %mul = shl nsw i64 %i.043, 2
276 %arrayidx2 = getelementptr inbounds float* %A, i64 %mul
277 %5 = load float* %arrayidx2, align 4
278 %mul3 = fmul fast float %0, %5
279 %add = fadd fast float %sum.042, %mul3
280 %add638 = or i64 %mul, 1
281 %arrayidx7 = getelementptr inbounds float* %A, i64 %add638
282 %6 = load float* %arrayidx7, align 4
283 %mul8 = fmul fast float %1, %6
284 %add9 = fadd fast float %add, %mul8
285 %add1239 = or i64 %mul, 2
286 %arrayidx13 = getelementptr inbounds float* %A, i64 %add1239
287 %7 = load float* %arrayidx13, align 4
288 %mul14 = fmul fast float %2, %7
289 %add15 = fadd fast float %add9, %mul14
290 %add1840 = or i64 %mul, 3
291 %arrayidx19 = getelementptr inbounds float* %A, i64 %add1840
292 %8 = load float* %arrayidx19, align 4
293 %mul20 = fmul fast float %3, %8
294 %add21 = fadd fast float %add15, %mul20
295 %inc = add nsw i64 %i.043, 1
296 %exitcond = icmp eq i64 %inc, %4
297 br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body
299 for.cond.for.end_crit_edge:
300 %phitmp = fptosi float %add21 to i32
304 %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
308 ; int foo(float * restrict A, float * restrict B, float * restrict C, int n) {
310 ; for (intptr_t i=0; i < n; ++i) {
311 ; C[i] = B[0] *A[i*4 ] +
319 ; CHECK-LABEL: store_red
320 ; CHECK: fmul <4 x float>
321 ; CHECK: shufflevector <4 x float>
323 define i32 @store_red(float* noalias %A, float* noalias %B, float* noalias %C, i32 %n) {
325 %cmp37 = icmp sgt i32 %n, 0
326 br i1 %cmp37, label %for.body.lr.ph, label %for.end
329 %arrayidx4 = getelementptr inbounds float* %B, i64 1
330 %arrayidx9 = getelementptr inbounds float* %B, i64 2
331 %arrayidx15 = getelementptr inbounds float* %B, i64 3
332 %0 = sext i32 %n to i64
336 %i.039 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
337 %C.addr.038 = phi float* [ %C, %for.body.lr.ph ], [ %incdec.ptr, %for.body ]
338 %1 = load float* %B, align 4
339 %mul = shl nsw i64 %i.039, 2
340 %arrayidx2 = getelementptr inbounds float* %A, i64 %mul
341 %2 = load float* %arrayidx2, align 4
342 %mul3 = fmul fast float %1, %2
343 %3 = load float* %arrayidx4, align 4
344 %add34 = or i64 %mul, 1
345 %arrayidx6 = getelementptr inbounds float* %A, i64 %add34
346 %4 = load float* %arrayidx6, align 4
347 %mul7 = fmul fast float %3, %4
348 %add8 = fadd fast float %mul3, %mul7
349 %5 = load float* %arrayidx9, align 4
350 %add1135 = or i64 %mul, 2
351 %arrayidx12 = getelementptr inbounds float* %A, i64 %add1135
352 %6 = load float* %arrayidx12, align 4
353 %mul13 = fmul fast float %5, %6
354 %add14 = fadd fast float %add8, %mul13
355 %7 = load float* %arrayidx15, align 4
356 %add1736 = or i64 %mul, 3
357 %arrayidx18 = getelementptr inbounds float* %A, i64 %add1736
358 %8 = load float* %arrayidx18, align 4
359 %mul19 = fmul fast float %7, %8
360 %add20 = fadd fast float %add14, %mul19
361 store float %add20, float* %C.addr.038, align 4
362 %incdec.ptr = getelementptr inbounds float* %C.addr.038, i64 1
363 %inc = add nsw i64 %i.039, 1
364 %exitcond = icmp eq i64 %inc, %0
365 br i1 %exitcond, label %for.end, label %for.body
372 ; void foo(double * restrict A, double * restrict B, double * restrict C,
374 ; for (intptr_t i=0; i < n; ++i) {
375 ; C[i] = B[0] *A[i*4 ] + B[1] *A[i*4+1];
379 ; CHECK-LABEL: store_red_double
380 ; CHECK: fmul <2 x double>
381 ; CHECK: extractelement <2 x double>
382 ; CHECK: extractelement <2 x double>
384 define void @store_red_double(double* noalias %A, double* noalias %B, double* noalias %C, i32 %n) {
386 %cmp17 = icmp sgt i32 %n, 0
387 br i1 %cmp17, label %for.body.lr.ph, label %for.end
390 %0 = load double* %B, align 8
391 %arrayidx4 = getelementptr inbounds double* %B, i64 1
392 %1 = load double* %arrayidx4, align 8
393 %2 = sext i32 %n to i64
397 %i.018 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
398 %mul = shl nsw i64 %i.018, 2
399 %arrayidx2 = getelementptr inbounds double* %A, i64 %mul
400 %3 = load double* %arrayidx2, align 8
401 %mul3 = fmul fast double %0, %3
402 %add16 = or i64 %mul, 1
403 %arrayidx6 = getelementptr inbounds double* %A, i64 %add16
404 %4 = load double* %arrayidx6, align 8
405 %mul7 = fmul fast double %1, %4
406 %add8 = fadd fast double %mul3, %mul7
407 %arrayidx9 = getelementptr inbounds double* %C, i64 %i.018
408 store double %add8, double* %arrayidx9, align 8
409 %inc = add nsw i64 %i.018, 1
410 %exitcond = icmp eq i64 %inc, %2
411 br i1 %exitcond, label %for.end, label %for.body