1; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 < %s | FileCheck %s
2
3target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
4
5; Float pattern:
6;   Check vectorization of reduction code which has an fadd instruction after
7;   an fcmp instruction which compares an array element and 0.
8;
9; float fcmp_0_fadd_select1(float * restrict x, const int N) {
10;   float sum = 0.
11;   for (int i = 0; i < N; ++i)
12;     if (x[i] > (float)0.)
13;       sum += x[i];
14;   return sum;
15; }
16
17; CHECK-LABEL: @fcmp_0_fadd_select1(
18; CHECK: %[[V1:.*]] = fcmp fast ogt <4 x float> %[[V0:.*]], zeroinitializer
19; CHECK: %[[V3:.*]] = fadd fast <4 x float> %[[V0]], %[[V2:.*]]
20; CHECK: select <4 x i1> %[[V1]], <4 x float> %[[V3]], <4 x float> %[[V2]]
21define float @fcmp_0_fadd_select1(float* noalias %x, i32 %N) nounwind readonly {
22entry:
23  %cmp.1 = icmp sgt i32 %N, 0
24  br i1 %cmp.1, label %for.header, label %for.end
25
26for.header:                                       ; preds = %entry
27  %zext = zext i32 %N to i64
28  br label %for.body
29
30for.body:                                         ; preds = %header, %for.body
31  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
32  %sum.1 = phi float [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
33  %arrayidx = getelementptr inbounds float, float* %x, i64 %indvars.iv
34  %0 = load float, float* %arrayidx, align 4
35  %cmp.2 = fcmp fast ogt float %0, 0.000000e+00
36  %add = fadd fast float %0, %sum.1
37  %sum.2 = select i1 %cmp.2, float %add, float %sum.1
38  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
39  %exitcond = icmp eq i64 %indvars.iv.next, %zext
40  br i1 %exitcond, label %for.end, label %for.body
41
42for.end:                                          ; preds = %for.body, %entry
43  %1 = phi float [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
44  ret float %1
45}
46
47; Double pattern:
48;   Check vectorization of reduction code which has an fadd instruction after
49;   an fcmp instruction which compares an array element and 0.
50;
51; double fcmp_0_fadd_select2(double * restrict x, const int N) {
52;   double sum = 0.
53;   for (int i = 0; i < N; ++i)
54;     if (x[i] > 0.)
55;       sum += x[i];
56;   return sum;
57; }
58
59; CHECK-LABEL: @fcmp_0_fadd_select2(
60; CHECK: %[[V1:.*]] = fcmp fast ogt <4 x double> %[[V0:.*]], zeroinitializer
61; CHECK: %[[V3:.*]] = fadd fast <4 x double> %[[V0]], %[[V2:.*]]
62; CHECK: select <4 x i1> %[[V1]], <4 x double> %[[V3]], <4 x double> %[[V2]]
63define double @fcmp_0_fadd_select2(double* noalias %x, i32 %N) nounwind readonly {
64entry:
65  %cmp.1 = icmp sgt i32 %N, 0
66  br i1 %cmp.1, label %for.header, label %for.end
67
68for.header:                                       ; preds = %entry
69  %zext = zext i32 %N to i64
70  br label %for.body
71
72for.body:                                         ; preds = %header, %for.body
73  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
74  %sum.1 = phi double [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
75  %arrayidx = getelementptr inbounds double, double* %x, i64 %indvars.iv
76  %0 = load double, double* %arrayidx, align 4
77  %cmp.2 = fcmp fast ogt double %0, 0.000000e+00
78  %add = fadd fast double %0, %sum.1
79  %sum.2 = select i1 %cmp.2, double %add, double %sum.1
80  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
81  %exitcond = icmp eq i64 %indvars.iv.next, %zext
82  br i1 %exitcond, label %for.end, label %for.body
83
84for.end:                                          ; preds = %for.body, %entry
85  %1 = phi double [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
86  ret double %1
87}
88
89; Float pattern:
90;   Check vectorization of reduction code which has an fadd instruction after
91;   an fcmp instruction which compares an array element and a floating-point
92;   value.
93;
94; float fcmp_val_fadd_select1(float * restrict x, float y, const int N) {
95;   float sum = 0.
96;   for (int i = 0; i < N; ++i)
97;     if (x[i] > y)
98;       sum += x[i];
99;   return sum;
100; }
101
102; CHECK-LABEL: @fcmp_val_fadd_select1(
103; CHECK: %[[V1:.*]] = fcmp fast ogt <4 x float> %[[V0:.*]], %broadcast.splat2
104; CHECK: %[[V3:.*]] = fadd fast <4 x float> %[[V0]], %[[V2:.*]]
105; CHECK: select <4 x i1> %[[V1]], <4 x float> %[[V3]], <4 x float> %[[V2]]
106define float @fcmp_val_fadd_select1(float* noalias %x, float %y, i32 %N) nounwind readonly {
107entry:
108  %cmp.1 = icmp sgt i32 %N, 0
109  br i1 %cmp.1, label %for.header, label %for.end
110
111for.header:                                       ; preds = %entry
112  %zext = zext i32 %N to i64
113  br label %for.body
114
115for.body:                                         ; preds = %header, %for.body
116  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
117  %sum.1 = phi float [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
118  %arrayidx = getelementptr inbounds float, float* %x, i64 %indvars.iv
119  %0 = load float, float* %arrayidx, align 4
120  %cmp.2 = fcmp fast ogt float %0, %y
121  %add = fadd fast float %0, %sum.1
122  %sum.2 = select i1 %cmp.2, float %add, float %sum.1
123  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
124  %exitcond = icmp eq i64 %indvars.iv.next, %zext
125  br i1 %exitcond, label %for.end, label %for.body
126
127for.end:                                          ; preds = %for.body, %entry
128  %1 = phi float [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
129  ret float %1
130}
131
132; Double pattern:
133;   Check vectorization of reduction code which has an fadd instruction after
134;   an fcmp instruction which compares an array element and a floating-point
135;   value.
136;
137; double fcmp_val_fadd_select2(double * restrict x, double y, const int N) {
138;   double sum = 0.
139;   for (int i = 0; i < N; ++i)
140;     if (x[i] > y)
141;       sum += x[i];
142;   return sum;
143; }
144
145; CHECK-LABEL: @fcmp_val_fadd_select2(
146; CHECK: %[[V1:.*]] = fcmp fast ogt <4 x double> %[[V0:.*]], %broadcast.splat2
147; CHECK: %[[V3:.*]] = fadd fast <4 x double> %[[V0]], %[[V2:.*]]
148; CHECK: select <4 x i1> %[[V1]], <4 x double> %[[V3]], <4 x double> %[[V2]]
149define double @fcmp_val_fadd_select2(double* noalias %x, double %y, i32 %N) nounwind readonly {
150entry:
151  %cmp.1 = icmp sgt i32 %N, 0
152  br i1 %cmp.1, label %for.header, label %for.end
153
154for.header:                                       ; preds = %entry
155  %zext = zext i32 %N to i64
156  br label %for.body
157
158for.body:                                         ; preds = %header, %for.body
159  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
160  %sum.1 = phi double [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
161  %arrayidx = getelementptr inbounds double, double* %x, i64 %indvars.iv
162  %0 = load double, double* %arrayidx, align 4
163  %cmp.2 = fcmp fast ogt double %0, %y
164  %add = fadd fast double %0, %sum.1
165  %sum.2 = select i1 %cmp.2, double %add, double %sum.1
166  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
167  %exitcond = icmp eq i64 %indvars.iv.next, %zext
168  br i1 %exitcond, label %for.end, label %for.body
169
170for.end:                                          ; preds = %for.body, %entry
171  %1 = phi double [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
172  ret double %1
173}
174
175; Float pattern:
176;   Check vectorization of reduction code which has an fadd instruction after
177;   an fcmp instruction which compares an array element and another array
178;   element.
179;
180; float fcmp_array_elm_fadd_select1(float * restrict x, float * restrict y,
181;                                   const int N) {
182;   float sum = 0.
183;   for (int i = 0; i < N; ++i)
184;     if (x[i] > y[i])
185;       sum += x[i];
186;   return sum;
187; }
188
189; CHECK-LABEL: @fcmp_array_elm_fadd_select1(
190; CHECK: %[[V2:.*]] = fcmp fast ogt <4 x float> %[[V0:.*]], %[[V1:.*]]
191; CHECK: %[[V4:.*]] = fadd fast <4 x float> %[[V0]], %[[V3:.*]]
192; CHECK: select <4 x i1> %[[V2]], <4 x float> %[[V4]], <4 x float> %[[V3]]
193define float @fcmp_array_elm_fadd_select1(float* noalias %x, float* noalias %y, i32 %N) nounwind readonly {
194entry:
195  %cmp.1 = icmp sgt i32 %N, 0
196  br i1 %cmp.1, label %for.header, label %for.end
197
198for.header:                                       ; preds = %entry
199  %zext = zext i32 %N to i64
200  br label %for.body
201
202for.body:                                         ; preds = %for.body, %for.header
203  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
204  %sum.1 = phi float [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
205  %arrayidx.1 = getelementptr inbounds float, float* %x, i64 %indvars.iv
206  %0 = load float, float* %arrayidx.1, align 4
207  %arrayidx.2 = getelementptr inbounds float, float* %y, i64 %indvars.iv
208  %1 = load float, float* %arrayidx.2, align 4
209  %cmp.2 = fcmp fast ogt float %0, %1
210  %add = fadd fast float %0, %sum.1
211  %sum.2 = select i1 %cmp.2, float %add, float %sum.1
212  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
213  %exitcond = icmp eq i64 %indvars.iv.next, %zext
214  br i1 %exitcond, label %for.end, label %for.body
215
216for.end:                                          ; preds = %for.body, %entry
217  %2 = phi float [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
218  ret float %2
219}
220
221; Double pattern:
222;   Check vectorization of reduction code which has an fadd instruction after
223;   an fcmp instruction which compares an array element and another array
224;   element.
225;
226; double fcmp_array_elm_fadd_select2(double * restrict x, double * restrict y,
227;                                    const int N) {
228;   double sum = 0.
229;   for (int i = 0; i < N; ++i)
230;     if (x[i] > y[i])
231;       sum += x[i];
232;   return sum;
233; }
234
235; CHECK-LABEL: @fcmp_array_elm_fadd_select2(
236; CHECK: %[[V2:.*]] = fcmp fast ogt <4 x double> %[[V0:.*]], %[[V1:.*]]
237; CHECK: %[[V4:.*]] = fadd fast <4 x double> %[[V0]], %[[V3:.*]]
238; CHECK: select <4 x i1> %[[V2]], <4 x double> %[[V4]], <4 x double> %[[V3]]
239define double @fcmp_array_elm_fadd_select2(double* noalias %x, double* noalias %y, i32 %N) nounwind readonly {
240entry:
241  %cmp.1 = icmp sgt i32 %N, 0
242  br i1 %cmp.1, label %for.header, label %for.end
243
244for.header:                                       ; preds = %entry
245  %zext = zext i32 %N to i64
246  br label %for.body
247
248for.body:                                         ; preds = %for.body, %for.header
249  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
250  %sum.1 = phi double [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
251  %arrayidx.1 = getelementptr inbounds double, double* %x, i64 %indvars.iv
252  %0 = load double, double* %arrayidx.1, align 4
253  %arrayidx.2 = getelementptr inbounds double, double* %y, i64 %indvars.iv
254  %1 = load double, double* %arrayidx.2, align 4
255  %cmp.2 = fcmp fast ogt double %0, %1
256  %add = fadd fast double %0, %sum.1
257  %sum.2 = select i1 %cmp.2, double %add, double %sum.1
258  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
259  %exitcond = icmp eq i64 %indvars.iv.next, %zext
260  br i1 %exitcond, label %for.end, label %for.body
261
262for.end:                                          ; preds = %for.body, %entry
263  %2 = phi double [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
264  ret double %2
265}
266
267; Float pattern:
268;   Check vectorization of reduction code which has an fsub instruction after
269;   an fcmp instruction which compares an array element and 0.
270;
271; float fcmp_0_fsub_select1(float * restrict x, const int N) {
272;   float sum = 0.
273;   for (int i = 0; i < N; ++i)
274;     if (x[i] > (float)0.)
275;       sum -= x[i];
276;   return sum;
277; }
278
279; CHECK-LABEL: @fcmp_0_fsub_select1(
280; CHECK: %[[V1:.*]] = fcmp ogt <4 x float> %[[V0:.*]], zeroinitializer
281; CHECK: %[[V3:.*]] = fsub <4 x float> %[[V2:.*]], %[[V0]]
282; CHECK: select <4 x i1> %[[V1]], <4 x float> %[[V3]], <4 x float> %[[V2]]
283define float @fcmp_0_fsub_select1(float* noalias %x, i32 %N) nounwind readonly {
284entry:
285  %cmp.1 = icmp sgt i32 %N, 0
286  br i1 %cmp.1, label %for.header, label %for.end
287
288for.header:                                       ; preds = %entry
289  %zext = zext i32 %N to i64
290  br label %for.body
291
292for.body:                                         ; preds = %for.body, %for.header
293  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
294  %sum.1 = phi float [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
295  %arrayidx = getelementptr inbounds float, float* %x, i64 %indvars.iv
296  %0 = load float, float* %arrayidx, align 4
297  %cmp.2 = fcmp ogt float %0, 0.000000e+00
298  %sub = fsub float %sum.1, %0
299  %sum.2 = select i1 %cmp.2, float %sub, float %sum.1
300  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
301  %exitcond = icmp eq i64 %indvars.iv.next, %zext
302  br i1 %exitcond, label %for.end, label %for.body
303
304for.end:                                          ; preds = %for.body, %entry
305  %1 = phi float [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
306  ret float %1
307}
308
309; Double pattern:
310;   Check vectorization of reduction code which has an fsub instruction after
311;   an fcmp instruction which compares an array element and 0.
312;
313; double fcmp_0_fsub_select2(double * restrict x, const int N) {
314;   double sum = 0.
315;   for (int i = 0; i < N; ++i)
316;     if (x[i] > 0.)
317;       sum -= x[i];
318;   return sum;
319; }
320
321; CHECK-LABEL: @fcmp_0_fsub_select2(
322; CHECK: %[[V1:.*]] = fcmp ogt <4 x double> %[[V0:.*]], zeroinitializer
323; CHECK: %[[V3:.*]] = fsub <4 x double> %[[V2:.*]], %[[V0]]
324; CHECK: select <4 x i1> %[[V1]], <4 x double> %[[V3]], <4 x double> %[[V2]]
325define double @fcmp_0_fsub_select2(double* noalias %x, i32 %N) nounwind readonly {
326entry:
327  %cmp.1 = icmp sgt i32 %N, 0
328  br i1 %cmp.1, label %for.header, label %for.end
329
330for.header:                                       ; preds = %entry
331  %zext = zext i32 %N to i64
332  br label %for.body
333
334for.body:                                         ; preds = %for.body, %for.header
335  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
336  %sum.1 = phi double [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
337  %arrayidx = getelementptr inbounds double, double* %x, i64 %indvars.iv
338  %0 = load double, double* %arrayidx, align 4
339  %cmp.2 = fcmp ogt double %0, 0.000000e+00
340  %sub = fsub double %sum.1, %0
341  %sum.2 = select i1 %cmp.2, double %sub, double %sum.1
342  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
343  %exitcond = icmp eq i64 %indvars.iv.next, %zext
344  br i1 %exitcond, label %for.end, label %for.body
345
346for.end:                                          ; preds = %for.body, %entry
347  %1 = phi double [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
348  ret double %1
349}
350
351; Float pattern:
352;   Check vectorization of reduction code which has an fmul instruction after
353;   an fcmp instruction which compares an array element and 0.
354;
355; float fcmp_0_fmult_select1(float * restrict x, const int N) {
356;   float sum = 0.
357;   for (int i = 0; i < N; ++i)
358;     if (x[i] > (float)0.)
359;       sum *= x[i];
360;   return sum;
361; }
362
363; CHECK-LABEL: @fcmp_0_fmult_select1(
364; CHECK: %[[V1:.*]] = fcmp ogt <4 x float> %[[V0:.*]], zeroinitializer
365; CHECK: %[[V3:.*]] = fmul <4 x float> %[[V2:.*]], %[[V0]]
366; CHECK: select <4 x i1> %[[V1]], <4 x float> %[[V3]], <4 x float> %[[V2]]
367define float @fcmp_0_fmult_select1(float* noalias %x, i32 %N) nounwind readonly {
368entry:
369  %cmp.1 = icmp sgt i32 %N, 0
370  br i1 %cmp.1, label %for.header, label %for.end
371
372for.header:                                       ; preds = %entry
373  %zext = zext i32 %N to i64
374  br label %for.body
375
376for.body:                                         ; preds = %for.body, %for.header
377  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
378  %sum.1 = phi float [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
379  %arrayidx = getelementptr inbounds float, float* %x, i64 %indvars.iv
380  %0 = load float, float* %arrayidx, align 4
381  %cmp.2 = fcmp ogt float %0, 0.000000e+00
382  %mult = fmul float %sum.1, %0
383  %sum.2 = select i1 %cmp.2, float %mult, float %sum.1
384  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
385  %exitcond = icmp eq i64 %indvars.iv.next, %zext
386  br i1 %exitcond, label %for.end, label %for.body
387
388for.end:                                          ; preds = %for.body, %entry
389  %1 = phi float [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
390  ret float %1
391}
392
393; Double pattern:
394;   Check vectorization of reduction code which has an fmul instruction after
395;   an fcmp instruction which compares an array element and 0.
396;
397; double fcmp_0_fmult_select2(double * restrict x, const int N) {
398;   double sum = 0.
399;   for (int i = 0; i < N; ++i)
400;     if (x[i] > 0.)
401;       sum *= x[i];
402;   return sum;
403; }
404
405; CHECK-LABEL: @fcmp_0_fmult_select2(
406; CHECK: %[[V1:.*]] = fcmp ogt <4 x double> %[[V0:.*]], zeroinitializer
407; CHECK: %[[V3:.*]] = fmul <4 x double> %[[V2:.*]], %[[V0]]
408; CHECK: select <4 x i1> %[[V1]], <4 x double> %[[V3]], <4 x double> %[[V2]]
409define double @fcmp_0_fmult_select2(double* noalias %x, i32 %N) nounwind readonly {
410entry:
411  %cmp.1 = icmp sgt i32 %N, 0
412  br i1 %cmp.1, label %for.header, label %for.end
413
414for.header:                                       ; preds = %entry
415  %zext = zext i32 %N to i64
416  br label %for.body
417
418for.body:                                         ; preds = %for.body, %for.header
419  %indvars.iv = phi i64 [ 0, %for.header ], [ %indvars.iv.next, %for.body ]
420  %sum.1 = phi double [ 0.000000e+00, %for.header ], [ %sum.2, %for.body ]
421  %arrayidx = getelementptr inbounds double, double* %x, i64 %indvars.iv
422  %0 = load double, double* %arrayidx, align 4
423  %cmp.2 = fcmp ogt double %0, 0.000000e+00
424  %mult = fmul double %sum.1, %0
425  %sum.2 = select i1 %cmp.2, double %mult, double %sum.1
426  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
427  %exitcond = icmp eq i64 %indvars.iv.next, %zext
428  br i1 %exitcond, label %for.end, label %for.body
429
430for.end:                                          ; preds = %for.body, %entry
431  %1 = phi double [ 0.000000e+00, %entry ], [ %sum.2, %for.body ]
432  ret double %1
433}
434
435; Float multi pattern
436;   Check vectorisation of reduction code with a pair of selects to different
437;   fadd patterns.
438;
439; float fcmp_multi(float *a, int n) {
440;   float sum=0.0;
441;   for (int i=0;i<n;i++) {
442;     if (a[i]>1.0)
443;       sum+=a[i];
444;     else if (a[i]<3.0)
445;       sum+=2*a[i];
446;     else
447;       sum+=3*a[i];
448;   }
449;   return sum;
450; }
451
452; CHECK-LABEL: @fcmp_multi(
453; CHECK: %[[C1:.*]] = fcmp ogt <4 x float> %[[V0:.*]], <float 1.000000e+00,
454; CHECK: %[[C2:.*]] = fcmp olt <4 x float> %[[V0]], <float 3.000000e+00,
455; CHECK-DAG: %[[M1:.*]] = fmul fast <4 x float> %[[V0]], <float 3.000000e+00,
456; CHECK-DAG: %[[M2:.*]] = fmul fast <4 x float> %[[V0]], <float 2.000000e+00,
457; CHECK: %[[C11:.*]] = xor <4 x i1> %[[C1]], <i1 true,
458; CHECK-DAG: %[[C12:.*]] = and <4 x i1> %[[C2]], %[[C11]]
459; CHECK-DAG: %[[C21:.*]] = xor <4 x i1> %[[C2]], <i1 true,
460; CHECK: %[[C22:.*]] = and <4 x i1> %[[C21]], %[[C11]]
461; CHECK: %[[S1:.*]] = select <4 x i1> %[[C22]], <4 x float> %[[M1]], <4 x float> %[[M2]]
462; CHECK: %[[S2:.*]] = select <4 x i1> %[[C1]], <4 x float> %[[V0]], <4 x float> %[[S1]]
463; CHECK: fadd fast <4 x float> %[[S2]],
464define float @fcmp_multi(float* nocapture readonly %a, i32 %n) nounwind readonly {
465entry:
466  %cmp10 = icmp sgt i32 %n, 0
467  br i1 %cmp10, label %for.body.preheader, label %for.end
468
469for.body.preheader:                               ; preds = %entry
470  %wide.trip.count = zext i32 %n to i64
471  br label %for.body
472
473for.body:                                         ; preds = %for.inc, %for.body.preheader
474  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.inc ]
475  %sum.011 = phi float [ 0.000000e+00, %for.body.preheader ], [ %sum.1, %for.inc ]
476  %arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
477  %0 = load float, float* %arrayidx, align 4
478  %cmp1 = fcmp ogt float %0, 1.000000e+00
479  br i1 %cmp1, label %for.inc, label %if.else
480
481if.else:                                          ; preds = %for.body
482  %cmp8 = fcmp olt float %0, 3.000000e+00
483  br i1 %cmp8, label %if.then10, label %if.else14
484
485if.then10:                                        ; preds = %if.else
486  %mul = fmul fast float %0, 2.000000e+00
487  br label %for.inc
488
489if.else14:                                        ; preds = %if.else
490  %mul17 = fmul fast float %0, 3.000000e+00
491  br label %for.inc
492
493for.inc:                                          ; preds = %for.body, %if.else14, %if.then10
494  %.pn = phi float [ %mul, %if.then10 ], [ %mul17, %if.else14 ], [ %0, %for.body ]
495  %sum.1 = fadd fast float %.pn, %sum.011
496  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
497  %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
498  br i1 %exitcond, label %for.end, label %for.body
499
500for.end:                                          ; preds = %for.inc, %entry
501  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %sum.1, %for.inc ]
502  ret float %sum.0.lcssa
503}
504
505; Float fadd + fsub patterns
506;   Check vectorisation of reduction code with a pair of selects to different
507;   instructions { fadd, fsub } but equivalent (change in constant).
508;
509; float fcmp_multi(float *a, int n) {
510;   float sum=0.0;
511;   for (int i=0;i<n;i++) {
512;     if (a[i]>1.0)
513;       sum+=a[i];
514;     else if (a[i]<3.0)
515;       sum-=a[i];
516;   }
517;   return sum;
518; }
519
520; CHECK-LABEL: @fcmp_fadd_fsub(
521; CHECK: %[[C1:.*]] = fcmp ogt <4 x float> %[[V0:.*]], <float 1.000000e+00,
522; CHECK: %[[C2:.*]] = fcmp olt <4 x float> %[[V0]], <float 3.000000e+00,
523; CHECK-DAG: %[[SUB:.*]] = fsub fast <4 x float>
524; CHECK-DAG: %[[ADD:.*]] = fadd fast <4 x float>
525; CHECK: %[[C11:.*]] = xor <4 x i1> %[[C1]], <i1 true,
526; CHECK-DAG: %[[C12:.*]] = and <4 x i1> %[[C2]], %[[C11]]
527; CHECK-DAG: %[[C21:.*]] = xor <4 x i1> %[[C2]], <i1 true,
528; CHECK: %[[C22:.*]] = and <4 x i1> %[[C21]], %[[C11]]
529; CHECK: %[[S1:.*]] = select <4 x i1> %[[C12]], <4 x float> %[[SUB]], <4 x float> %[[ADD]]
530; CHECK: %[[S2:.*]] = select <4 x i1> %[[C22]], {{.*}} <4 x float> %[[S1]]
531define float @fcmp_fadd_fsub(float* nocapture readonly %a, i32 %n) nounwind readonly {
532entry:
533  %cmp9 = icmp sgt i32 %n, 0
534  br i1 %cmp9, label %for.body.preheader, label %for.end
535
536for.body.preheader:                               ; preds = %entry
537  %wide.trip.count = zext i32 %n to i64
538  br label %for.body
539
540for.body:                                         ; preds = %for.inc, %for.body.preheader
541  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.inc ]
542  %sum.010 = phi float [ 0.000000e+00, %for.body.preheader ], [ %sum.1, %for.inc ]
543  %arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
544  %0 = load float, float* %arrayidx, align 4
545  %cmp1 = fcmp ogt float %0, 1.000000e+00
546  br i1 %cmp1, label %if.then, label %if.else
547
548if.then:                                          ; preds = %for.body
549  %add = fadd fast float %0, %sum.010
550  br label %for.inc
551
552if.else:                                          ; preds = %for.body
553  %cmp8 = fcmp olt float %0, 3.000000e+00
554  br i1 %cmp8, label %if.then10, label %for.inc
555
556if.then10:                                        ; preds = %if.else
557  %sub = fsub fast float %sum.010, %0
558  br label %for.inc
559
560for.inc:                                          ; preds = %if.then, %if.then10, %if.else
561  %sum.1 = phi float [ %add, %if.then ], [ %sub, %if.then10 ], [ %sum.010, %if.else ]
562  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
563  %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
564  br i1 %exitcond, label %for.end, label %for.body
565
566for.end:                                          ; preds = %for.inc, %entry
567  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %sum.1, %for.inc ]
568  ret float %sum.0.lcssa
569}
570
571; Float fadd + fmul patterns
572;   Check lack of vectorisation of reduction code with a pair of non-compatible
573;   instructions { fadd, fmul }.
574;
575; float fcmp_multi(float *a, int n) {
576;   float sum=0.0;
577;   for (int i=0;i<n;i++) {
578;     if (a[i]>1.0)
579;       sum+=a[i];
580;     else if (a[i]<3.0)
581;       sum*=a[i];
582;   }
583;   return sum;
584; }
585
586; CHECK-LABEL: @fcmp_fadd_fmul(
587; CHECK-NOT: <4 x float>
588define float @fcmp_fadd_fmul(float* nocapture readonly %a, i32 %n) nounwind readonly {
589entry:
590  %cmp9 = icmp sgt i32 %n, 0
591  br i1 %cmp9, label %for.body.preheader, label %for.end
592
593for.body.preheader:                               ; preds = %entry
594  %wide.trip.count = zext i32 %n to i64
595  br label %for.body
596
597for.body:                                         ; preds = %for.inc, %for.body.preheader
598  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.inc ]
599  %sum.010 = phi float [ 0.000000e+00, %for.body.preheader ], [ %sum.1, %for.inc ]
600  %arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
601  %0 = load float, float* %arrayidx, align 4
602  %cmp1 = fcmp ogt float %0, 1.000000e+00
603  br i1 %cmp1, label %if.then, label %if.else
604
605if.then:                                          ; preds = %for.body
606  %add = fadd fast float %0, %sum.010
607  br label %for.inc
608
609if.else:                                          ; preds = %for.body
610  %cmp8 = fcmp olt float %0, 3.000000e+00
611  br i1 %cmp8, label %if.then10, label %for.inc
612
613if.then10:                                        ; preds = %if.else
614  %mul = fmul fast float %0, %sum.010
615  br label %for.inc
616
617for.inc:                                          ; preds = %if.then, %if.then10, %if.else
618  %sum.1 = phi float [ %add, %if.then ], [ %mul, %if.then10 ], [ %sum.010, %if.else ]
619  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
620  %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
621  br i1 %exitcond, label %for.end, label %for.body
622
623for.end:                                          ; preds = %for.inc, %entry
624  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %sum.1, %for.inc ]
625  ret float %sum.0.lcssa
626}
627
628; Float fadd + store patterns
629;   Check lack of vectorisation of reduction code with a store back, given it
630;   has loop dependency on a[i].
631;
632; float fcmp_store_back(float a[], int LEN) {
633;     float sum = 0.0;
634;     for (int i = 0; i < LEN; i++) {
635;       sum += a[i];
636;       a[i] = sum;
637;     }
638;     return sum;
639; }
640
641; CHECK-LABEL: @fcmp_store_back(
642; CHECK-NOT: <4 x float>
643define float @fcmp_store_back(float* nocapture %a, i32 %LEN) nounwind readonly {
644entry:
645  %cmp7 = icmp sgt i32 %LEN, 0
646  br i1 %cmp7, label %for.body.preheader, label %for.end
647
648for.body.preheader:                               ; preds = %entry
649  %wide.trip.count = zext i32 %LEN to i64
650  br label %for.body
651
652for.body:                                         ; preds = %for.body, %for.body.preheader
653  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
654  %sum.08 = phi float [ 0.000000e+00, %for.body.preheader ], [ %add, %for.body ]
655  %arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
656  %0 = load float, float* %arrayidx, align 4
657  %add = fadd fast float %0, %sum.08
658  store float %add, float* %arrayidx, align 4
659  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
660  %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
661  br i1 %exitcond, label %for.end, label %for.body
662
663for.end:                                          ; preds = %for.body, %entry
664  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add, %for.body ]
665  ret float %sum.0.lcssa
666}
667