[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / AArch64 / strict-fadd.ll
blob0722ac3783e2b0b7819d65fee48e1df60f40cffb
1 ; RUN: opt < %s -loop-vectorize -mtriple aarch64-unknown-linux-gnu -force-ordered-reductions=false -hints-allow-reordering=false -S 2>%t | FileCheck %s --check-prefix=CHECK-NOT-VECTORIZED
2 ; RUN: opt < %s -loop-vectorize -mtriple aarch64-unknown-linux-gnu -force-ordered-reductions=false -hints-allow-reordering=true  -S 2>%t | FileCheck %s --check-prefix=CHECK-UNORDERED
3 ; RUN: opt < %s -loop-vectorize -mtriple aarch64-unknown-linux-gnu -force-ordered-reductions=true  -hints-allow-reordering=false -S 2>%t | FileCheck %s --check-prefix=CHECK-ORDERED
4 ; RUN: opt < %s -loop-vectorize -mtriple aarch64-unknown-linux-gnu -force-ordered-reductions=true  -hints-allow-reordering=true  -S 2>%t | FileCheck %s --check-prefix=CHECK-UNORDERED
5 ; RUN: opt < %s -loop-vectorize -mtriple aarch64-unknown-linux-gnu -hints-allow-reordering=false -S 2>%t | FileCheck %s --check-prefix=CHECK-NOT-VECTORIZED
7 define float @fadd_strict(float* noalias nocapture readonly %a, i64 %n) {
8 ; CHECK-ORDERED-LABEL: @fadd_strict
9 ; CHECK-ORDERED: vector.body:
10 ; CHECK-ORDERED: %[[VEC_PHI:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX:.*]], %vector.body ]
11 ; CHECK-ORDERED: %[[LOAD:.*]] = load <8 x float>, <8 x float>*
12 ; CHECK-ORDERED: %[[RDX]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[VEC_PHI]], <8 x float> %[[LOAD]])
13 ; CHECK-ORDERED: for.end
14 ; CHECK-ORDERED: %[[PHI:.*]] = phi float [ %[[SCALAR:.*]], %for.body ], [ %[[RDX]], %middle.block ]
15 ; CHECK-ORDERED: ret float %[[PHI]]
17 ; CHECK-UNORDERED-LABEL: @fadd_strict
18 ; CHECK-UNORDERED: vector.body
19 ; CHECK-UNORDERED: %[[VEC_PHI:.*]] = phi <8 x float> [ <float 0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[FADD_VEC:.*]], %vector.body ]
20 ; CHECK-UNORDERED: %[[LOAD_VEC:.*]] = load <8 x float>, <8 x float>*
21 ; CHECK-UNORDERED: %[[FADD_VEC]] = fadd <8 x float> %[[LOAD_VEC]], %[[VEC_PHI]]
22 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
23 ; CHECK-UNORDERED: middle.block
24 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float -0.000000e+00, <8 x float> %[[FADD_VEC]])
25 ; CHECK-UNORDERED: for.body
26 ; CHECK-UNORDERED: %[[LOAD:.*]] = load float, float*
27 ; CHECK-UNORDERED: %[[FADD:.*]] = fadd float %[[LOAD]], {{.*}}
28 ; CHECK-UNORDERED: for.end
29 ; CHECK-UNORDERED: %[[RES:.*]] = phi float [ %[[FADD]], %for.body ], [ %[[RDX]], %middle.block ]
30 ; CHECK-UNORDERED: ret float %[[RES]]
32 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_strict
33 ; CHECK-NOT-VECTORIZED-NOT: vector.body
35 entry:
36   br label %for.body
38 for.body:
39   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
40   %sum.07 = phi float [ 0.000000e+00, %entry ], [ %add, %for.body ]
41   %arrayidx = getelementptr inbounds float, float* %a, i64 %iv
42   %0 = load float, float* %arrayidx, align 4
43   %add = fadd float %0, %sum.07
44   %iv.next = add nuw nsw i64 %iv, 1
45   %exitcond.not = icmp eq i64 %iv.next, %n
46   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0
48 for.end:
49   ret float %add
52 define float @fadd_strict_unroll(float* noalias nocapture readonly %a, i64 %n) {
53 ; CHECK-ORDERED-LABEL: @fadd_strict_unroll
54 ; CHECK-ORDERED: vector.body:
55 ; CHECK-ORDERED: %[[VEC_PHI1:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX4:.*]], %vector.body ]
56 ; CHECK-ORDERED-NOT: phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX4]], %vector.body ]
57 ; CHECK-ORDERED: %[[LOAD1:.*]] = load <8 x float>, <8 x float>*
58 ; CHECK-ORDERED: %[[LOAD2:.*]] = load <8 x float>, <8 x float>*
59 ; CHECK-ORDERED: %[[LOAD3:.*]] = load <8 x float>, <8 x float>*
60 ; CHECK-ORDERED: %[[LOAD4:.*]] = load <8 x float>, <8 x float>*
61 ; CHECK-ORDERED: %[[RDX1:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[VEC_PHI1]], <8 x float> %[[LOAD1]])
62 ; CHECK-ORDERED: %[[RDX2:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX1]], <8 x float> %[[LOAD2]])
63 ; CHECK-ORDERED: %[[RDX3:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX2]], <8 x float> %[[LOAD3]])
64 ; CHECK-ORDERED: %[[RDX4]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX3]], <8 x float> %[[LOAD4]])
65 ; CHECK-ORDERED: for.end
66 ; CHECK-ORDERED: %[[PHI:.*]] = phi float [ %[[SCALAR:.*]], %for.body ], [ %[[RDX4]], %middle.block ]
67 ; CHECK-ORDERED: ret float %[[PHI]]
69 ; CHECK-UNORDERED-LABEL: @fadd_strict_unroll
70 ; CHECK-UNORDERED: vector.body
71 ; CHECK-UNORDERED:  %[[VEC_PHI1:.*]] = phi <8 x float> [ <float 0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD1:.*]], %vector.body ]
72 ; CHECK-UNORDERED:  %[[VEC_PHI2:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD2:.*]], %vector.body ]
73 ; CHECK-UNORDERED:  %[[VEC_PHI3:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD3:.*]], %vector.body ]
74 ; CHECK-UNORDERED:  %[[VEC_PHI4:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD4:.*]], %vector.body ]
75 ; CHECK-UNORDERED: %[[VEC_LOAD1:.*]] = load <8 x float>, <8 x float>*
76 ; CHECK-UNORDERED: %[[VEC_LOAD2:.*]] = load <8 x float>, <8 x float>*
77 ; CHECK-UNORDERED: %[[VEC_LOAD3:.*]] = load <8 x float>, <8 x float>*
78 ; CHECK-UNORDERED: %[[VEC_LOAD4:.*]] = load <8 x float>, <8 x float>*
79 ; CHECK-UNORDERED: %[[VEC_FADD1]] = fadd <8 x float> %[[VEC_LOAD1]], %[[VEC_PHI1]]
80 ; CHECK-UNORDERED: %[[VEC_FADD2]] = fadd <8 x float> %[[VEC_LOAD2]], %[[VEC_PHI2]]
81 ; CHECK-UNORDERED: %[[VEC_FADD3]] = fadd <8 x float> %[[VEC_LOAD3]], %[[VEC_PHI3]]
82 ; CHECK-UNORDERED: %[[VEC_FADD4]] = fadd <8 x float> %[[VEC_LOAD4]], %[[VEC_PHI4]]
83 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
84 ; CHECK-UNORDERED: middle.block
85 ; CHECK-UNORDERED: %[[BIN_RDX1:.*]] = fadd <8 x float> %[[VEC_FADD2]], %[[VEC_FADD1]]
86 ; CHECK-UNORDERED: %[[BIN_RDX2:.*]] = fadd <8 x float> %[[VEC_FADD3]], %[[BIN_RDX1]]
87 ; CHECK-UNORDERED: %[[BIN_RDX3:.*]] = fadd <8 x float> %[[VEC_FADD4]], %[[BIN_RDX2]]
88 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float -0.000000e+00, <8 x float> %[[BIN_RDX3]])
89 ; CHECK-UNORDERED: for.body
90 ; CHECK-UNORDERED: %[[LOAD:.*]] = load float, float*
91 ; CHECK-UNORDERED: %[[FADD:.*]] = fadd float %[[LOAD]], {{.*}}
92 ; CHECK-UNORDERED: for.end
93 ; CHECK-UNORDERED: %[[RES:.*]] = phi float [ %[[FADD]], %for.body ], [ %[[RDX]], %middle.block ]
94 ; CHECK-UNORDERED: ret float %[[RES]]
96 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_strict_unroll
97 ; CHECK-NOT-VECTORIZED-NOT: vector.body
99 entry:
100   br label %for.body
102 for.body:
103   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
104   %sum.07 = phi float [ 0.000000e+00, %entry ], [ %add, %for.body ]
105   %arrayidx = getelementptr inbounds float, float* %a, i64 %iv
106   %0 = load float, float* %arrayidx, align 4
107   %add = fadd float %0, %sum.07
108   %iv.next = add nuw nsw i64 %iv, 1
109   %exitcond.not = icmp eq i64 %iv.next, %n
110   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !1
112 for.end:
113   ret float %add
116 ; An additional test for unrolling where we need the last value of the reduction, i.e:
117 ; float sum = 0, sum2;
118 ; for(int i=0; i<N; ++i) {
119 ;   sum += ptr[i];
120 ;   *ptr2 = sum + 42;
121 ; }
122 ; return sum;
124 define float @fadd_strict_unroll_last_val(float* noalias nocapture readonly %a, float* noalias nocapture readonly %b, i64 %n) {
125 ; CHECK-ORDERED-LABEL: @fadd_strict_unroll_last_val
126 ; CHECK-ORDERED: vector.body
127 ; CHECK-ORDERED: %[[VEC_PHI1:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX4:.*]], %vector.body ]
128 ; CHECK-ORDERED-NOT: phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX4]], %vector.body ]
129 ; CHECK-ORDERED: %[[LOAD1:.*]] = load <8 x float>, <8 x float>*
130 ; CHECK-ORDERED: %[[LOAD2:.*]] = load <8 x float>, <8 x float>*
131 ; CHECK-ORDERED: %[[LOAD3:.*]] = load <8 x float>, <8 x float>*
132 ; CHECK-ORDERED: %[[LOAD4:.*]] = load <8 x float>, <8 x float>*
133 ; CHECK-ORDERED: %[[RDX1:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[VEC_PHI1]], <8 x float> %[[LOAD1]])
134 ; CHECK-ORDERED: %[[RDX2:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX1]], <8 x float> %[[LOAD2]])
135 ; CHECK-ORDERED: %[[RDX3:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX2]], <8 x float> %[[LOAD3]])
136 ; CHECK-ORDERED: %[[RDX4]] = call float @llvm.vector.reduce.fadd.v8f32(float %[[RDX3]], <8 x float> %[[LOAD4]])
137 ; CHECK-ORDERED: for.body
138 ; CHECK-ORDERED: %[[SUM_PHI:.*]] = phi float [ %[[FADD:.*]], %for.body ], [ {{.*}}, %scalar.ph ]
139 ; CHECK-ORDERED: %[[LOAD5:.*]] = load float, float*
140 ; CHECK-ORDERED: %[[FADD]] =  fadd float %[[SUM_PHI]], %[[LOAD5]]
141 ; CHECK-ORDERED: for.cond.cleanup
142 ; CHECK-ORDERED: %[[FADD_LCSSA:.*]] = phi float [ %[[FADD]], %for.body ], [ %[[RDX4]], %middle.block ]
143 ; CHECK-ORDERED: %[[FADD_42:.*]] = fadd float %[[FADD_LCSSA]], 4.200000e+01
144 ; CHECK-ORDERED: store float %[[FADD_42]], float* %b
145 ; CHECK-ORDERED: for.end
146 ; CHECK-ORDERED: %[[SUM_LCSSA:.*]] = phi float [ %[[FADD_LCSSA]], %for.cond.cleanup ], [ 0.000000e+00, %entry ]
147 ; CHECK-ORDERED: ret float %[[SUM_LCSSA]]
149 ; CHECK-UNORDERED-LABEL: @fadd_strict_unroll_last_val
150 ; CHECK-UNORDERED: vector.body
151 ; CHECK-UNORDERED: %[[VEC_PHI1:.*]] = phi <8 x float> [ <float 0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD1:.*]], %vector.body ]
152 ; CHECK-UNORDERED: %[[VEC_PHI2:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD2:.*]], %vector.body ]
153 ; CHECK-UNORDERED: %[[VEC_PHI3:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD3:.*]], %vector.body ]
154 ; CHECK-UNORDERED: %[[VEC_PHI4:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD4:.*]], %vector.body ]
155 ; CHECK-UNORDERED: %[[VEC_LOAD1:.*]] = load <8 x float>, <8 x float>*
156 ; CHECK-UNORDERED: %[[VEC_LOAD2:.*]] = load <8 x float>, <8 x float>*
157 ; CHECK-UNORDERED: %[[VEC_LOAD3:.*]] = load <8 x float>, <8 x float>*
158 ; CHECK-UNORDERED: %[[VEC_LOAD4:.*]] = load <8 x float>, <8 x float>*
159 ; CHECK-UNORDERED: %[[VEC_FADD1]] = fadd <8 x float> %[[VEC_PHI1]], %[[VEC_LOAD1]]
160 ; CHECK-UNORDERED: %[[VEC_FADD2]] = fadd <8 x float> %[[VEC_PHI2]], %[[VEC_LOAD2]]
161 ; CHECK-UNORDERED: %[[VEC_FADD3]] = fadd <8 x float> %[[VEC_PHI3]], %[[VEC_LOAD3]]
162 ; CHECK-UNORDERED: %[[VEC_FADD4]] = fadd <8 x float> %[[VEC_PHI4]], %[[VEC_LOAD4]]
163 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
164 ; CHECK-UNORDERED: middle.block
165 ; CHECK-UNORDERED: %[[BIN_RDX1:.*]] = fadd <8 x float> %[[VEC_FADD2]], %[[VEC_FADD1]]
166 ; CHECK-UNORDERED: %[[BIN_RDX2:.*]] = fadd <8 x float> %[[VEC_FADD3]], %[[BIN_RDX1]]
167 ; CHECK-UNORDERED: %[[BIN_RDX3:.*]] = fadd <8 x float> %[[VEC_FADD4]], %[[BIN_RDX2]]
168 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float -0.000000e+00, <8 x float> %[[BIN_RDX3]])
169 ; CHECK-UNORDERED: for.body
170 ; CHECK-UNORDERED: %[[LOAD:.*]] = load float, float*
171 ; CHECK-UNORDERED: %[[FADD:.*]] = fadd float {{.*}}, %[[LOAD]]
172 ; CHECK-UNORDERED: for.cond.cleanup
173 ; CHECK-UNORDERED: %[[FADD_LCSSA:.*]] = phi float [ %[[FADD]], %for.body ], [ %[[RDX]], %middle.block ]
174 ; CHECK-UNORDERED: %[[FADD_42:.*]] = fadd float %[[FADD_LCSSA]], 4.200000e+01
175 ; CHECK-UNORDERED: store float %[[FADD_42]], float* %b
176 ; CHECK-UNORDERED: for.end
177 ; CHECK-UNORDERED: %[[SUM_LCSSA:.*]] = phi float [ %[[FADD_LCSSA]], %for.cond.cleanup ], [ 0.000000e+00, %entry ]
178 ; CHECK-UNORDERED: ret float %[[SUM_LCSSA]]
180 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_strict_unroll_last_val
181 ; CHECK-NOT-VECTORIZED-NOT: vector.body
183 entry:
184   %cmp = icmp sgt i64 %n, 0
185   br i1 %cmp, label %for.body, label %for.end
187 for.body:
188   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
189   %sum = phi float [ 0.000000e+00, %entry ], [ %fadd, %for.body ]
190   %arrayidx = getelementptr inbounds float, float* %a, i64 %iv
191   %0 = load float, float* %arrayidx, align 4
192   %fadd = fadd float %sum, %0
193   %iv.next = add nuw nsw i64 %iv, 1
194   %exitcond.not = icmp eq i64 %iv.next, %n
195   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1
197 for.cond.cleanup:
198   %fadd.lcssa = phi float [ %fadd, %for.body ]
199   %fadd2 = fadd float %fadd.lcssa, 4.200000e+01
200   store float %fadd2, float* %b, align 4
201   br label %for.end
203 for.end:
204   %sum.lcssa = phi float [ %fadd.lcssa, %for.cond.cleanup ], [ 0.000000e+00, %entry ]
205   ret float %sum.lcssa
208 define void @fadd_strict_interleave(float* noalias nocapture readonly %a, float* noalias nocapture readonly %b, i64 %n) {
209 ; CHECK-ORDERED-LABEL: @fadd_strict_interleave
210 ; CHECK-ORDERED: entry
211 ; CHECK-ORDERED: %[[ARRAYIDX:.*]] = getelementptr inbounds float, float* %a, i64 1
212 ; CHECK-ORDERED: %[[LOAD1:.*]] = load float, float* %a
213 ; CHECK-ORDERED: %[[LOAD2:.*]] = load float, float* %[[ARRAYIDX]]
214 ; CHECK-ORDERED: vector.body
215 ; CHECK-ORDERED: %[[VEC_PHI1:.*]] = phi float [ %[[LOAD2]], %vector.ph ], [ %[[RDX2:.*]], %vector.body ]
216 ; CHECK-ORDERED: %[[VEC_PHI2:.*]] = phi float [ %[[LOAD1]], %vector.ph ], [ %[[RDX1:.*]], %vector.body ]
217 ; CHECK-ORDERED: %[[WIDE_LOAD:.*]] = load <8 x float>, <8 x float>*
218 ; CHECK-ORDERED: %[[STRIDED1:.*]] = shufflevector <8 x float> %[[WIDE_LOAD]], <8 x float> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
219 ; CHECK-ORDERED: %[[STRIDED2:.*]] = shufflevector <8 x float> %[[WIDE_LOAD]], <8 x float> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
220 ; CHECK-ORDERED: %[[RDX1]] = call float @llvm.vector.reduce.fadd.v4f32(float %[[VEC_PHI2]], <4 x float> %[[STRIDED1]])
221 ; CHECK-ORDERED: %[[RDX2]] = call float @llvm.vector.reduce.fadd.v4f32(float %[[VEC_PHI1]], <4 x float> %[[STRIDED2]])
222 ; CHECK-ORDERED: for.end
223 ; CHECK-ORDERED: ret void
225 ; CHECK-UNORDERED-LABEL: @fadd_strict_interleave
226 ; CHECK-UNORDERED: %[[ARRAYIDX:.*]] = getelementptr inbounds float, float* %a, i64 1
227 ; CHECK-UNORDERED: %[[LOADA1:.*]] = load float, float* %a
228 ; CHECK-UNORDERED: %[[LOADA2:.*]] = load float, float* %[[ARRAYIDX]]
229 ; CHECK-UNORDERED: vector.ph
230 ; CHECK-UNORDERED: %[[INS2:.*]] = insertelement <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, float %[[LOADA2]], i32 0
231 ; CHECK-UNORDERED: %[[INS1:.*]] = insertelement <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, float %[[LOADA1]], i32 0
232 ; CHECK-UNORDERED: vector.body
233 ; CHECK-UNORDERED: %[[VEC_PHI2:.*]] = phi <4 x float> [ %[[INS2]], %vector.ph ], [ %[[VEC_FADD2:.*]], %vector.body ]
234 ; CHECK-UNORDERED: %[[VEC_PHI1:.*]] = phi <4 x float> [ %[[INS1]], %vector.ph ], [ %[[VEC_FADD1:.*]], %vector.body ]
235 ; CHECK-UNORDERED: %[[WIDE_LOAD:.*]] = load <8 x float>, <8 x float>*
236 ; CHECK-UNORDERED: %[[STRIDED1:.*]] = shufflevector <8 x float> %[[WIDE_LOAD]], <8 x float> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
237 ; CHECK-UNORDERED: %[[STRIDED2:.*]] = shufflevector <8 x float> %[[WIDE_LOAD]], <8 x float> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
238 ; CHECK-UNORDERED: %[[VEC_FADD1]] = fadd <4 x float> %[[STRIDED1:.*]], %[[VEC_PHI1]]
239 ; CHECK-UNORDERED: %[[VEC_FADD2]] = fadd <4 x float> %[[STRIDED2:.*]], %[[VEC_PHI2]]
240 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
241 ; CHECK-UNORDERED: middle.block
242 ; CHECK-UNORDERED: %[[RDX1:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> %[[VEC_FADD1]])
243 ; CHECK-UNORDERED: %[[RDX2:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> %[[VEC_FADD2]])
244 ; CHECK-UNORDERED: for.body
245 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load float, float*
246 ; CHECK-UNORDERED: %[[FADD1:.*]] = fadd float %[[LOAD1]], {{.*}}
247 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
248 ; CHECK-UNORDERED: %[[FADD2:.*]] = fadd float %[[LOAD2]], {{.*}}
249 ; CHECK-UNORDERED: for.end
250 ; CHECK-UNORDERED: %[[SUM1:.*]] = phi float [ %[[FADD1]], %for.body ], [ %[[RDX1]], %middle.block ]
251 ; CHECK-UNORDERED: %[[SUM2:.*]] = phi float [ %[[FADD2]], %for.body ], [ %[[RDX2]], %middle.block ]
252 ; CHECK-UNORDERED: store float %[[SUM1]]
253 ; CHECK-UNORDERED: store float %[[SUM2]]
254 ; CHECK-UNORDERED: ret void
256 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_strict_interleave
257 ; CHECK-NOT-VECTORIZED-NOT: vector.body
259 entry:
260   %arrayidxa = getelementptr inbounds float, float* %a, i64 1
261   %a1 = load float, float* %a, align 4
262   %a2 = load float, float* %arrayidxa, align 4
263   br label %for.body
265 for.body:
266   %add.phi1 = phi float [ %a2, %entry ], [ %add2, %for.body ]
267   %add.phi2 = phi float [ %a1, %entry ], [ %add1, %for.body ]
268   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
269   %arrayidxb1 = getelementptr inbounds float, float* %b, i64 %iv
270   %0 = load float, float* %arrayidxb1, align 4
271   %add1 = fadd float %0, %add.phi2
272   %or = or i64 %iv, 1
273   %arrayidxb2 = getelementptr inbounds float, float* %b, i64 %or
274   %1 = load float, float* %arrayidxb2, align 4
275   %add2 = fadd float %1, %add.phi1
276   %iv.next = add nuw nsw i64 %iv, 2
277   %exitcond.not = icmp eq i64 %iv.next, %n
278   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !2
280 for.end:
281   store float %add1, float* %a, align 4
282   store float %add2, float* %arrayidxa, align 4
283   ret void
286 define float @fadd_of_sum(float* noalias nocapture readonly %a, float* noalias nocapture readonly %b, i64 %n) {
287 ; CHECK-ORDERED-LABEL: @fadd_of_sum
288 ; CHECK-ORDERED: vector.body
289 ; CHECK-ORDERED: %[[VEC_PHI1:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX:.*]], %vector.body ]
290 ; CHECK-ORDERED: %[[LOAD1:.*]] = load <4 x float>, <4 x float>*
291 ; CHECK-ORDERED: %[[LOAD2:.*]] = load <4 x float>, <4 x float>*
292 ; CHECK-ORDERED: %[[ADD:.*]] = fadd <4 x float> %[[LOAD1]], %[[LOAD2]]
293 ; CHECK-ORDERED: %[[RDX]] = call float @llvm.vector.reduce.fadd.v4f32(float %[[VEC_PHI1]], <4 x float> %[[ADD]])
294 ; CHECK-ORDERED: for.end.loopexit
295 ; CHECK-ORDERED: %[[EXIT_PHI:.*]] = phi float [ %[[SCALAR:.*]], %for.body ], [ %[[RDX]], %middle.block ]
296 ; CHECK-ORDERED: for.end
297 ; CHECK-ORDERED: %[[PHI:.*]] = phi float [ 0.000000e+00, %entry ], [ %[[EXIT_PHI]], %for.end.loopexit ]
298 ; CHECK-ORDERED: ret float %[[PHI]]
300 ; CHECK-UNORDERED-LABEL: @fadd_of_sum
301 ; CHECK-UNORDERED: vector.body
302 ; CHECK-UNORDERED: %[[VEC_PHI:.*]] = phi <4 x float> [ <float 0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD2:.*]], %vector.body ]
303 ; CHECK-UNORDERED: %[[VEC_LOAD1:.*]] = load <4 x float>, <4 x float>*
304 ; CHECK-UNORDERED: %[[VEC_LOAD2:.*]] = load <4 x float>, <4 x float>*
305 ; CHECK-UNORDERED: %[[VEC_FADD1:.*]] = fadd <4 x float> %[[VEC_LOAD1]], %[[VEC_LOAD2]]
306 ; CHECK-UNORDERED: %[[VEC_FADD2]] = fadd <4 x float> %[[VEC_PHI]], %[[VEC_FADD1]]
307 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
308 ; CHECK-UNORDERED: middle.block
309 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> %[[VEC_FADD2]])
310 ; CHECK-UNORDERED: for.body
311 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load float, float*
312 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
313 ; CHECK-UNORDERED: %[[FADD1:.*]] = fadd float %[[LOAD1]], %[[LOAD2]]
314 ; CHECK-UNORDERED: %[[FADD2:.*]] = fadd float {{.*}}, %[[FADD1]]
315 ; CHECK-UNORDERED: for.end.loopexit
316 ; CHECK-UNORDERED: %[[EXIT:.*]] = phi float [ %[[FADD2]], %for.body ], [ %[[RDX]], %middle.block ]
317 ; CHECK-UNORDERED: for.end
318 ; CHECK-UNORDERED: %[[SUM:.*]] = phi float [ 0.000000e+00, %entry ], [ %[[EXIT]], %for.end.loopexit ]
319 ; CHECK-UNORDERED: ret float %[[SUM]]
321 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_of_sum
322 ; CHECK-NOT-VECTORIZED-NOT: vector.body
324 entry:
325   %arrayidx = getelementptr inbounds float, float* %a, i64 1
326   %0 = load float, float* %arrayidx, align 4
327   %cmp1 = fcmp ogt float %0, 5.000000e-01
328   br i1 %cmp1, label %for.body, label %for.end
330 for.body:                                      ; preds = %for.body
331   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
332   %res.014 = phi float [ 0.000000e+00, %entry ], [ %rdx, %for.body ]
333   %arrayidx2 = getelementptr inbounds float, float* %a, i64 %iv
334   %1 = load float, float* %arrayidx2, align 4
335   %arrayidx4 = getelementptr inbounds float, float* %b, i64 %iv
336   %2 = load float, float* %arrayidx4, align 4
337   %add = fadd float %1, %2
338   %rdx = fadd float %res.014, %add
339   %iv.next = add nuw nsw i64 %iv, 1
340   %exitcond.not = icmp eq i64 %iv.next, %n
341   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !2
343 for.end:                                 ; preds = %for.body, %entry
344   %res = phi float [ 0.000000e+00, %entry ], [ %rdx, %for.body ]
345   ret float %res
348 define float @fadd_conditional(float* noalias nocapture readonly %a, float* noalias nocapture readonly %b, i64 %n) {
349 ; CHECK-ORDERED-LABEL: @fadd_conditional
350 ; CHECK-ORDERED: vector.body:
351 ; CHECK-ORDERED: %[[PHI:.*]] = phi float [ 1.000000e+00, %vector.ph ], [ %[[RDX:.*]], %pred.load.continue6 ]
352 ; CHECK-ORDERED: %[[LOAD1:.*]] = load <4 x float>, <4 x float>*
353 ; CHECK-ORDERED: %[[FCMP1:.*]] = fcmp une <4 x float> %[[LOAD1]], zeroinitializer
354 ; CHECK-ORDERED: %[[EXTRACT:.*]] = extractelement <4 x i1> %[[FCMP1]], i32 0
355 ; CHECK-ORDERED: br i1 %[[EXTRACT]], label %pred.load.if, label %pred.load.continue
356 ; CHECK-ORDERED: pred.load.continue6
357 ; CHECK-ORDERED: %[[PHI1:.*]] = phi <4 x float> [ %[[PHI0:.*]], %pred.load.continue4 ], [ %[[INS_ELT:.*]], %pred.load.if5 ]
358 ; CHECK-ORDERED: %[[XOR:.*]] =  xor <4 x i1> %[[FCMP1]], <i1 true, i1 true, i1 true, i1 true>
359 ; CHECK-ORDERED: %[[PRED:.*]] = select <4 x i1> %[[XOR]], <4 x float> <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00>, <4 x float> %[[PHI1]]
360 ; CHECK-ORDERED: %[[RDX]] = call float @llvm.vector.reduce.fadd.v4f32(float %[[PHI]], <4 x float> %[[PRED]])
361 ; CHECK-ORDERED: for.body
362 ; CHECK-ORDERED: %[[RES_PHI:.*]] = phi float [ %[[MERGE_RDX:.*]], %scalar.ph ], [ %[[FADD:.*]], %for.inc ]
363 ; CHECK-ORDERED: %[[LOAD2:.*]] = load float, float*
364 ; CHECK-ORDERED: %[[FCMP2:.*]] = fcmp une float %[[LOAD2]], 0.000000e+00
365 ; CHECK-ORDERED: br i1 %[[FCMP2]], label %if.then, label %for.inc
366 ; CHECK-ORDERED: if.then
367 ; CHECK-ORDERED: %[[LOAD3:.*]] = load float, float*
368 ; CHECK-ORDERED: br label %for.inc
369 ; CHECK-ORDERED: for.inc
370 ; CHECK-ORDERED: %[[PHI2:.*]] = phi float [ %[[LOAD3]], %if.then ], [ 3.000000e+00, %for.body ]
371 ; CHECK-ORDERED: %[[FADD]] = fadd float %[[RES_PHI]], %[[PHI2]]
372 ; CHECK-ORDERED: for.end
373 ; CHECK-ORDERED: %[[RDX_PHI:.*]] = phi float [ %[[FADD]], %for.inc ], [ %[[RDX]], %middle.block ]
374 ; CHECK-ORDERED: ret float %[[RDX_PHI]]
376 ; CHECK-UNORDERED-LABEL: @fadd_conditional
377 ; CHECK-UNORDERED: vector.body
378 ; CHECK-UNORDERED: %[[PHI:.*]] = phi <4 x float> [ <float 1.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD:.*]], %pred.load.continue6 ]
379 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load <4 x float>, <4 x float>*
380 ; CHECK-UNORDERED: %[[FCMP1:.*]] = fcmp une <4 x float> %[[LOAD1]], zeroinitializer
381 ; CHECK-UNORDERED: %[[EXTRACT:.*]] = extractelement <4 x i1> %[[FCMP1]], i32 0
382 ; CHECK-UNORDERED: br i1 %[[EXTRACT]], label %pred.load.if, label %pred.load.continue
383 ; CHECK-UNORDERED: pred.load.continue6
384 ; CHECK-UNORDERED: %[[XOR:.*]] =  xor <4 x i1> %[[FCMP1]], <i1 true, i1 true, i1 true, i1 true>
385 ; CHECK-UNORDERED: %[[PRED:.*]] = select <4 x i1> %[[XOR]], <4 x float> <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00>, <4 x float> %[[PRED_PHI:.*]]
386 ; CHECK-UNORDERED: %[[VEC_FADD]] = fadd <4 x float> %[[PHI]], %[[PRED]]
387 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
388 ; CHECK-UNORDERED: middle.block
389 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> %[[VEC_FADD]])
390 ; CHECK-UNORDERED: for.body
391 ; CHECK-UNORDERED: %[[RES_PHI:.*]] = phi float [ %[[MERGE_RDX:.*]], %scalar.ph ], [ %[[FADD:.*]], %for.inc ]
392 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
393 ; CHECK-UNORDERED: %[[FCMP2:.*]] = fcmp une float %[[LOAD2]], 0.000000e+00
394 ; CHECK-UNORDERED: br i1 %[[FCMP2]], label %if.then, label %for.inc
395 ; CHECK-UNORDERED: if.then
396 ; CHECK-UNORDERED: %[[LOAD3:.*]] = load float, float*
397 ; CHECK-UNORDERED: for.inc
398 ; CHECK-UNORDERED: %[[PHI:.*]] = phi float [ %[[LOAD3]], %if.then ], [ 3.000000e+00, %for.body ]
399 ; CHECK-UNORDERED: %[[FADD]] = fadd float %[[RES_PHI]], %[[PHI]]
400 ; CHECK-UNORDERED: for.end
401 ; CHECK-UNORDERED: %[[RDX_PHI:.*]] = phi float [ %[[FADD]], %for.inc ], [ %[[RDX]], %middle.block ]
402 ; CHECK-UNORDERED: ret float %[[RDX_PHI]]
404 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_conditional
405 ; CHECK-NOT-VECTORIZED-NOT: vector.body
407 entry:
408   br label %for.body
410 for.body:                                      ; preds = %for.body
411   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.inc ]
412   %res = phi float [ 1.000000e+00, %entry ], [ %fadd, %for.inc ]
413   %arrayidx = getelementptr inbounds float, float* %b, i64 %iv
414   %0 = load float, float* %arrayidx, align 4
415   %tobool = fcmp une float %0, 0.000000e+00
416   br i1 %tobool, label %if.then, label %for.inc
418 if.then:                                      ; preds = %for.body
419   %arrayidx2 = getelementptr inbounds float, float* %a, i64 %iv
420   %1 = load float, float* %arrayidx2, align 4
421   br label %for.inc
423 for.inc:
424   %phi = phi float [ %1, %if.then ], [ 3.000000e+00, %for.body ]
425   %fadd = fadd float %res, %phi
426   %iv.next = add nuw nsw i64 %iv, 1
427   %exitcond.not = icmp eq i64 %iv.next, %n
428   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !2
430 for.end:
431   %rdx = phi float [ %fadd, %for.inc ]
432   ret float %rdx
435 ; Test to check masking correct, using the "llvm.loop.vectorize.predicate.enable" attribute
436 define float @fadd_predicated(float* noalias nocapture %a, i64 %n) {
437 ; CHECK-ORDERED-LABEL: @fadd_predicated
438 ; CHECK-ORDERED: vector.ph
439 ; CHECK-ORDERED: %[[TRIP_MINUS_ONE:.*]] = sub i64 %n, 1
440 ; CHECK-ORDERED: %[[BROADCAST_INS:.*]] = insertelement <2 x i64> poison, i64 %[[TRIP_MINUS_ONE]], i32 0
441 ; CHECK-ORDERED: %[[SPLAT:.*]] = shufflevector <2 x i64> %[[BROADCAST_INS]], <2 x i64> poison, <2 x i32> zeroinitializer
442 ; CHECK-ORDERED: vector.body
443 ; CHECK-ORDERED: %[[RDX_PHI:.*]] =  phi float [ 0.000000e+00, %vector.ph ], [ %[[RDX:.*]], %pred.load.continue2 ]
444 ; CHECK-ORDERED: pred.load.continue2
445 ; CHECK-ORDERED: %[[PHI:.*]] = phi <2 x float> [ %[[PHI0:.*]], %pred.load.continue ], [ %[[INS_ELT:.*]], %pred.load.if1 ]
446 ; CHECK-ORDERED: %[[MASK:.*]] = select <2 x i1> %0, <2 x float> %[[PHI]], <2 x float> <float -0.000000e+00, float -0.000000e+00>
447 ; CHECK-ORDERED: %[[RDX]] = call float @llvm.vector.reduce.fadd.v2f32(float %[[RDX_PHI]], <2 x float> %[[MASK]])
448 ; CHECK-ORDERED: for.end:
449 ; CHECK-ORDERED: %[[RES_PHI:.*]] = phi float [ %[[FADD:.*]], %for.body ], [ %[[RDX]], %middle.block ]
450 ; CHECK-ORDERED: ret float %[[RES_PHI]]
452 ; CHECK-UNORDERED-LABEL: @fadd_predicated
453 ; CHECK-UNORDERED: vector.ph
454 ; CHECK-UNORDERED: %[[TRIP_MINUS_ONE:.*]] = sub i64 %n, 1
455 ; CHECK-UNORDERED: %[[BROADCAST_INS:.*]] = insertelement <2 x i64> poison, i64 %[[TRIP_MINUS_ONE]], i32 0
456 ; CHECK-UNORDERED: %[[SPLAT:.*]] = shufflevector <2 x i64> %[[BROADCAST_INS]], <2 x i64> poison, <2 x i32> zeroinitializer
457 ; CHECK-UNORDERED: vector.body
458 ; CHECK-UNORDERED: %[[RDX_PHI:.*]] =  phi <2 x float> [ <float 0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[FADD:.*]], %pred.load.continue2 ]
459 ; CHECK-UNORDERED: %[[ICMP:.*]] = icmp ule <2 x i64> %vec.ind, %[[SPLAT]]
460 ; CHECK-UNORDERED: pred.load.continue2
461 ; CHECK-UNORDERED: %[[FADD]] = fadd <2 x float> %[[RDX_PHI]], {{.*}}
462 ; CHECK-UNORDERED: %[[MASK:.*]] = select <2 x i1> %[[ICMP]], <2 x float> %[[FADD]], <2 x float> %[[RDX_PHI]]
463 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
464 ; CHECK-UNORDERED: middle.block
465 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v2f32(float -0.000000e+00, <2 x float> %[[MASK]])
466 ; CHECK-UNORDERED: for.body
467 ; CHECK-UNORDERED: %[[LOAD:.*]] = load float, float*
468 ; CHECK-UNORDERED: %[[FADD2:.*]] = fadd float {{.*}}, %[[LOAD]]
469 ; CHECK-UNORDERED: for.end
470 ; CHECK-UNORDERED: %[[SUM:.*]] = phi float [ %[[FADD2]], %for.body ], [ %[[RDX]], %middle.block ]
471 ; CHECK-UNORDERED: ret float %[[SUM]]
473 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_predicated
474 ; CHECK-NOT-VECTORIZED-NOT: vector.body
476 entry:
477   br label %for.body
479 for.body:                                           ; preds = %entry, %for.body
480   %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
481   %sum.02 = phi float [ %l7, %for.body ], [ 0.000000e+00, %entry ]
482   %l2 = getelementptr inbounds float, float* %a, i64 %iv
483   %l3 = load float, float* %l2, align 4
484   %l7 = fadd float %sum.02, %l3
485   %iv.next = add i64 %iv, 1
486   %exitcond = icmp eq i64 %iv.next, %n
487   br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !3
489 for.end:                                            ; preds = %for.body
490   %sum.0.lcssa = phi float [ %l7, %for.body ]
491   ret float %sum.0.lcssa
494 ; Negative test - loop contains multiple fadds which we cannot safely reorder
495 define float @fadd_multiple(float* noalias nocapture %a, float* noalias nocapture %b, i64 %n) {
496 ; CHECK-ORDERED-LABEL: @fadd_multiple
497 ; CHECK-ORDERED-NOT: vector.body
499 ; CHECK-UNORDERED-LABEL: @fadd_multiple
500 ; CHECK-UNORDERED: vector.body
501 ; CHECK-UNORDERED: %[[PHI:.*]] = phi <8 x float> [ <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD2:.*]], %vector.body ]
502 ; CHECK-UNORDERED: %[[VEC_LOAD1:.*]] = load <8 x float>, <8 x float>
503 ; CHECK-UNORDERED: %[[VEC_FADD1:.*]] = fadd <8 x float> %[[PHI]], %[[VEC_LOAD1]]
504 ; CHECK-UNORDERED: %[[VEC_LOAD2:.*]] = load <8 x float>, <8 x float>
505 ; CHECK-UNORDERED: %[[VEC_FADD2]] = fadd <8 x float> %[[VEC_FADD1]], %[[VEC_LOAD2]]
506 ; CHECK-UNORDERED: middle.block
507 ; CHECK-UNORDERED: %[[RDX:.*]] = call float @llvm.vector.reduce.fadd.v8f32(float -0.000000e+00, <8 x float> %[[VEC_FADD2]])
508 ; CHECK-UNORDERED: for.body
509 ; CHECK-UNORDERED: %[[SUM:.*]] = phi float [ %bc.merge.rdx, %scalar.ph ], [ %[[FADD2:.*]], %for.body ]
510 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load float, float*
511 ; CHECK-UNORDERED: %[[FADD1:.*]] = fadd float %sum, %[[LOAD1]]
512 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
513 ; CHECK-UNORDERED: %[[FADD2]] = fadd float %[[FADD1]], %[[LOAD2]]
514 ; CHECK-UNORDERED: for.end
515 ; CHECK-UNORDERED: %[[RET:.*]] = phi float [ %[[FADD2]], %for.body ], [ %[[RDX]], %middle.block ]
516 ; CHECK-UNORDERED: ret float %[[RET]]
518 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_multiple
519 ; CHECK-NOT-VECTORIZED-NOT: vector.body
521 entry:
522   br label %for.body
524 for.body:                                         ; preds = %entry, %for.body
525   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
526   %sum = phi float [ -0.000000e+00, %entry ], [ %add3, %for.body ]
527   %arrayidx = getelementptr inbounds float, float* %a, i64 %iv
528   %0 = load float, float* %arrayidx, align 4
529   %add = fadd float %sum, %0
530   %arrayidx2 = getelementptr inbounds float, float* %b, i64 %iv
531   %1 = load float, float* %arrayidx2, align 4
532   %add3 = fadd float %add, %1
533   %iv.next = add nuw nsw i64 %iv, 1
534   %exitcond.not = icmp eq i64 %iv.next, %n
535   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0
537 for.end:                                         ; preds = %for.body
538   %rdx = phi float [ %add3, %for.body ]
539   ret float %rdx
542 ; Tests with both a floating point reduction & induction, e.g.
544 ;float fp_iv_rdx_loop(float *values, float init, float * __restrict__ A, int N) {
545 ;  float fp_inc = 2.0;
546 ;  float x = init;
547 ;  float sum = 0.0;
548 ;  for (int i=0; i < N; ++i) {
549 ;    A[i] = x;
550 ;    x += fp_inc;
551 ;    sum += values[i];
552 ;  }
553 ;  return sum;
557 ; Strict reduction could be performed in-loop, but ordered FP induction variables are not supported
558 ; Note: This test does not use metadata hints, and as such we should not expect the CHECK-UNORDERED case to vectorize, even
559 ; with the -hints-allow-reordering flag set to true.
560 define float @induction_and_reduction(float* nocapture readonly %values, float %init, float* noalias nocapture %A, i64 %N) {
561 ; CHECK-ORDERED-LABEL: @induction_and_reduction
562 ; CHECK-ORDERED-NOT: vector.body
564 ; CHECK-UNORDERED-LABEL: @induction_and_reduction
565 ; CHECK-UNORDERED-NOT: vector.body
567 ; CHECK-NOT-VECTORIZED-LABEL: @induction_and_reduction
568 ; CHECK-NOT-VECTORIZED-NOT: vector.body
570 entry:
571   br label %for.body
573 for.body:
574   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
575   %sum.015 = phi float [ 0.000000e+00, %entry ], [ %add3, %for.body ]
576   %x.014 = phi float [ %init, %entry ], [ %add, %for.body ]
577   %arrayidx = getelementptr inbounds float, float* %A, i64 %iv
578   store float %x.014, float* %arrayidx, align 4
579   %add = fadd float %x.014, 2.000000e+00
580   %arrayidx2 = getelementptr inbounds float, float* %values, i64 %iv
581   %0 = load float, float* %arrayidx2, align 4
582   %add3 = fadd float %sum.015, %0
583   %iv.next = add nuw nsw i64 %iv, 1
584   %exitcond.not = icmp eq i64 %iv.next, %N
585   br i1 %exitcond.not, label %for.end, label %for.body
587 for.end:
588   ret float %add3
591 ; As above, but with the FP induction being unordered (fast) the loop can be vectorized with strict reductions
592 define float @fast_induction_and_reduction(float* nocapture readonly %values, float %init, float* noalias nocapture %A, i64 %N) {
593 ; CHECK-ORDERED-LABEL: @fast_induction_and_reduction
594 ; CHECK-ORDERED: vector.ph
595 ; CHECK-ORDERED: %[[INDUCTION:.*]] = fadd fast <4 x float> {{.*}}, <float 0.000000e+00, float 2.000000e+00, float 4.000000e+00, float 6.000000e+00>
596 ; CHECK-ORDERED: vector.body
597 ; CHECK-ORDERED: %[[RDX_PHI:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[FADD2:.*]], %vector.body ]
598 ; CHECK-ORDERED: %[[IND_PHI:.*]] = phi <4 x float> [ %[[INDUCTION]], %vector.ph ], [ %[[VEC_IND_NEXT:.*]], %vector.body ]
599 ; CHECK-ORDERED: %[[LOAD1:.*]] = load <4 x float>, <4 x float>*
600 ; CHECK-ORDERED: %[[FADD1:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float %[[RDX_PHI]], <4 x float> %[[LOAD1]])
601 ; CHECK-ORDERED: %[[VEC_IND_NEXT]] = fadd fast <4 x float> %[[IND_PHI]], <float 8.000000e+00, float 8.000000e+00, float 8.000000e+00, float 8.000000e+00>
602 ; CHECK-ORDERED: for.body
603 ; CHECK-ORDERED: %[[RDX_SUM_PHI:.*]] = phi float [ {{.*}}, %scalar.ph ], [ %[[FADD2:.*]], %for.body ]
604 ; CHECK-ORDERED: %[[IND_SUM_PHI:.*]] = phi fast float [ {{.*}}, %scalar.ph ], [ %[[ADD_IND:.*]], %for.body ]
605 ; CHECK-ORDERED: store float %[[IND_SUM_PHI]], float*
606 ; CHECK-ORDERED: %[[ADD_IND]] = fadd fast float %[[IND_SUM_PHI]], 2.000000e+00
607 ; CHECK-ORDERED: %[[LOAD2:.*]] = load float, float*
608 ; CHECK-ORDERED: %[[FADD2]] = fadd float %[[RDX_SUM_PHI]], %[[LOAD2]]
609 ; CHECK-ORDERED: for.end
610 ; CHECK-ORDERED: %[[RES_PHI:.*]] = phi float [ %[[FADD2]], %for.body ], [ %[[FADD1]], %middle.block ]
611 ; CHECK-ORDERED: ret float %[[RES_PHI]]
613 ; CHECK-UNORDERED-LABEL: @fast_induction_and_reduction
614 ; CHECK-UNORDERED: vector.ph
615 ; CHECK-UNORDERED: %[[INDUCTION:.*]] = fadd fast <4 x float> {{.*}}, <float 0.000000e+00, float 2.000000e+00, float 4.000000e+00, float 6.000000e+00>
616 ; CHECK-UNORDERED: vector.body
617 ; CHECK-UNORDERED: %[[RDX_PHI:.*]] = phi <4 x float> [ <float 0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vector.ph ], [ %[[VEC_FADD:.*]], %vector.body ]
618 ; CHECK-UNORDERED: %[[IND_PHI:.*]] = phi <4 x float> [ %[[INDUCTION]], %vector.ph ], [ %[[VEC_IND_NEXT:.*]], %vector.body ]
619 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load <4 x float>, <4 x float>*
620 ; CHECK-UNORDERED: %[[VEC_FADD]] = fadd <4 x float> %[[RDX_PHI]], %[[LOAD1]]
621 ; CHECK-UNORDERED: %[[VEC_IND_NEXT]] = fadd fast <4 x float> %[[IND_PHI]], <float 8.000000e+00, float 8.000000e+00, float 8.000000e+00, float 8.000000e+00>
622 ; CHECK-UNORDERED: middle.block:
623 ; CHECK-UNORDERED: %[[VEC_RDX:.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> %[[VEC_FADD]])
624 ; CHECK-UNORDERED: for.body:
625 ; CHECK-UNORDERED: %[[RDX_SUM_PHI:.*]] = phi float [ {{.*}}, %scalar.ph ], [ %[[FADD:.*]], %for.body ]
626 ; CHECK-UNORDERED: %[[IND_SUM_PHI:.*]] = phi fast float [ {{.*}}, %scalar.ph ], [ %[[ADD_IND:.*]], %for.body ]
627 ; CHECK-UNORDERED: store float %[[IND_SUM_PHI]], float*
628 ; CHECK-UNORDERED: %[[ADD_IND]] = fadd fast float %[[IND_SUM_PHI]], 2.000000e+00
629 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
630 ; CHECK-UNORDERED: %[[FADD]] = fadd float %[[RDX_SUM_PHI]], %[[LOAD2]]
631 ; CHECK-UNORDERED: for.end
632 ; CHECK-UNORDERED: %[[RES_PHI:.*]] = phi float [ %[[FADD]], %for.body ], [ %[[VEC_RDX]], %middle.block ]
633 ; CHECK-UNORDERED: ret float %[[RES_PHI]]
635 ; CHECK-NOT-VECTORIZED-LABEL: @fast_induction_and_reduction
636 ; CHECK-NOT-VECTORIZED-NOT: vector.body
638 entry:
639   br label %for.body
641 for.body:
642   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
643   %sum.015 = phi float [ 0.000000e+00, %entry ], [ %add3, %for.body ]
644   %x.014 = phi fast float [ %init, %entry ], [ %add, %for.body ]
645   %arrayidx = getelementptr inbounds float, float* %A, i64 %iv
646   store float %x.014, float* %arrayidx, align 4
647   %add = fadd fast float %x.014, 2.000000e+00
648   %arrayidx2 = getelementptr inbounds float, float* %values, i64 %iv
649   %0 = load float, float* %arrayidx2, align 4
650   %add3 = fadd float %sum.015, %0
651   %iv.next = add nuw nsw i64 %iv, 1
652   %exitcond.not = icmp eq i64 %iv.next, %N
653   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !2
655 for.end:
656   ret float %add3
659 ; The FP induction is fast, but here we can't vectorize as only one of the reductions is an FAdd that can be performed in-loop
660 ; Note: This test does not use metadata hints, and as such we should not expect the CHECK-UNORDERED case to vectorize, even
661 ; with the -hints-allow-reordering flag set to true.
662 define float @fast_induction_unordered_reduction(float* nocapture readonly %values, float %init, float* noalias nocapture %A, float* noalias nocapture %B, i64 %N) {
664 ; CHECK-ORDERED-LABEL: @fast_induction_unordered_reduction
665 ; CHECK-ORDERED-NOT: vector.body
667 ; CHECK-UNORDERED-LABEL: @fast_induction_unordered_reduction
668 ; CHECK-UNORDERED-NOT: vector.body
670 ; CHECK-NOT-VECTORIZED-LABEL: @fast_induction_unordered_reduction
671 ; CHECK-NOT-VECTORIZED-NOT: vector.body
673 entry:
674   br label %for.body
676 for.body:
677   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
678   %sum2.023 = phi float [ 3.000000e+00, %entry ], [ %mul, %for.body ]
679   %sum.022 = phi float [ 0.000000e+00, %entry ], [ %add3, %for.body ]
680   %x.021 = phi float [ %init, %entry ], [ %add, %for.body ]
681   %arrayidx = getelementptr inbounds float, float* %A, i64 %iv
682   store float %x.021, float* %arrayidx, align 4
683   %add = fadd fast float %x.021, 2.000000e+00
684   %arrayidx2 = getelementptr inbounds float, float* %values, i64 %iv
685   %0 = load float, float* %arrayidx2, align 4
686   %add3 = fadd float %sum.022, %0
687   %mul = fmul float %sum2.023, %0
688   %iv.next = add nuw nsw i64 %iv, 1
689   %exitcond.not = icmp eq i64 %iv.next, %N
690   br i1 %exitcond.not, label %for.end, label %for.body
692 for.end:
693   %add6 = fadd float %add3, %mul
694   ret float %add6
697 ; Test reductions for a VF of 1 and a UF > 1.
698 define float @fadd_scalar_vf(float* noalias nocapture readonly %a, i64 %n) {
699 ; CHECK-ORDERED-LABEL: @fadd_scalar_vf
700 ; CHECK-ORDERED: vector.body
701 ; CHECK-ORDERED: %[[VEC_PHI:.*]] = phi float [ 0.000000e+00, {{.*}} ], [ %[[FADD4:.*]], %vector.body ]
702 ; CHECK-ORDERED: %[[LOAD1:.*]] = load float, float*
703 ; CHECK-ORDERED: %[[LOAD2:.*]] = load float, float*
704 ; CHECK-ORDERED: %[[LOAD3:.*]] = load float, float*
705 ; CHECK-ORDERED: %[[LOAD4:.*]] = load float, float*
706 ; CHECK-ORDERED: %[[FADD1:.*]] = fadd float %[[VEC_PHI]], %[[LOAD1]]
707 ; CHECK-ORDERED: %[[FADD2:.*]] = fadd float %[[FADD1]], %[[LOAD2]]
708 ; CHECK-ORDERED: %[[FADD3:.*]] = fadd float %[[FADD2]], %[[LOAD3]]
709 ; CHECK-ORDERED: %[[FADD4]] = fadd float %[[FADD3]], %[[LOAD4]]
710 ; CHECK-ORDERED-NOT: call float @llvm.vector.reduce.fadd
711 ; CHECK-ORDERED: scalar.ph
712 ; CHECK-ORDERED: %[[MERGE_RDX:.*]] = phi float [ 0.000000e+00, %entry ], [ %[[FADD4]], %middle.block ]
713 ; CHECK-ORDERED: for.body
714 ; CHECK-ORDERED: %[[SUM_PHI:.*]] = phi float [ %[[MERGE_RDX]], %scalar.ph ], [ %[[FADD5:.*]], %for.body ]
715 ; CHECK-ORDERED: %[[LOAD5:.*]] = load float, float*
716 ; CHECK-ORDERED: %[[FADD5]] = fadd float %[[LOAD5]], %[[SUM_PHI]]
717 ; CHECK-ORDERED: for.end
718 ; CHECK-ORDERED: %[[RES_PHI:.*]] = phi float [ %[[FADD5]], %for.body ], [ %[[FADD4]], %middle.block ]
719 ; CHECK-ORDERED: ret float %[[RES_PHI]]
721 ; CHECK-UNORDERED-LABEL: @fadd_scalar_vf
722 ; CHECK-UNORDERED: vector.body
723 ; CHECK-UNORDERED: %[[VEC_PHI1:.*]] = phi float [ 0.000000e+00, %vector.ph ], [ %[[FADD1:.*]], %vector.body ]
724 ; CHECK-UNORDERED: %[[VEC_PHI2:.*]] = phi float [ -0.000000e+00, %vector.ph ], [ %[[FADD2:.*]], %vector.body ]
725 ; CHECK-UNORDERED: %[[VEC_PHI3:.*]] = phi float [ -0.000000e+00, %vector.ph ], [ %[[FADD3:.*]], %vector.body ]
726 ; CHECK-UNORDERED: %[[VEC_PHI4:.*]] = phi float [ -0.000000e+00, %vector.ph ], [ %[[FADD4:.*]], %vector.body ]
727 ; CHECK-UNORDERED: %[[LOAD1:.*]] = load float, float*
728 ; CHECK-UNORDERED: %[[LOAD2:.*]] = load float, float*
729 ; CHECK-UNORDERED: %[[LOAD3:.*]] = load float, float*
730 ; CHECK-UNORDERED: %[[LOAD4:.*]] = load float, float*
731 ; CHECK-UNORDERED: %[[FADD1]] = fadd float %[[LOAD1]], %[[VEC_PHI1]]
732 ; CHECK-UNORDERED: %[[FADD2]] = fadd float %[[LOAD2]], %[[VEC_PHI2]]
733 ; CHECK-UNORDERED: %[[FADD3]] = fadd float %[[LOAD3]], %[[VEC_PHI3]]
734 ; CHECK-UNORDERED: %[[FADD4]] = fadd float %[[LOAD4]], %[[VEC_PHI4]]
735 ; CHECK-UNORDERED-NOT: call float @llvm.vector.reduce.fadd
736 ; CHECK-UNORDERED: middle.block
737 ; CHECK-UNORDERED: %[[BIN_RDX1:.*]] = fadd float %[[FADD2]], %[[FADD1]]
738 ; CHECK-UNORDERED: %[[BIN_RDX2:.*]] = fadd float %[[FADD3]], %[[BIN_RDX1]]
739 ; CHECK-UNORDERED: %[[BIN_RDX3:.*]] = fadd float %[[FADD4]], %[[BIN_RDX2]]
740 ; CHECK-UNORDERED: scalar.ph
741 ; CHECK-UNORDERED: %[[MERGE_RDX:.*]] = phi float [ 0.000000e+00, %entry ], [ %[[BIN_RDX3]], %middle.block ]
742 ; CHECK-UNORDERED: for.body
743 ; CHECK-UNORDERED: %[[SUM_PHI:.*]] = phi float [ %[[MERGE_RDX]], %scalar.ph ], [ %[[FADD5:.*]], %for.body ]
744 ; CHECK-UNORDERED: %[[LOAD5:.*]] = load float, float*
745 ; CHECK-UNORDERED: %[[FADD5]] = fadd float %[[LOAD5]], %[[SUM_PHI]]
746 ; CHECK-UNORDERED: for.end
747 ; CHECK-UNORDERED: %[[RES_PHI:.*]] = phi float [ %[[FADD5]], %for.body ], [ %[[BIN_RDX3]], %middle.block ]
748 ; CHECK-UNORDERED: ret float %[[RES_PHI]]
750 ; CHECK-NOT-VECTORIZED-LABEL: @fadd_scalar_vf
751 ; CHECK-NOT-VECTORIZED-NOT: @vector.body
753 entry:
754   br label %for.body
756 for.body:
757   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
758   %sum.07 = phi float [ 0.000000e+00, %entry ], [ %add, %for.body ]
759   %arrayidx = getelementptr inbounds float, float* %a, i64 %iv
760   %0 = load float, float* %arrayidx, align 4
761   %add = fadd float %0, %sum.07
762   %iv.next = add nuw nsw i64 %iv, 1
763   %exitcond.not = icmp eq i64 %iv.next, %n
764   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !4
766 for.end:
767   ret float %add
770 !0 = distinct !{!0, !5, !9, !11}
771 !1 = distinct !{!1, !5, !10, !11}
772 !2 = distinct !{!2, !6, !9, !11}
773 !3 = distinct !{!3, !7, !9, !11, !12}
774 !4 = distinct !{!4, !8, !10, !11}
775 !5 = !{!"llvm.loop.vectorize.width", i32 8}
776 !6 = !{!"llvm.loop.vectorize.width", i32 4}
777 !7 = !{!"llvm.loop.vectorize.width", i32 2}
778 !8 = !{!"llvm.loop.vectorize.width", i32 1}
779 !9 = !{!"llvm.loop.interleave.count", i32 1}
780 !10 = !{!"llvm.loop.interleave.count", i32 4}
781 !11 = !{!"llvm.loop.vectorize.enable", i1 true}
782 !12 = !{!"llvm.loop.vectorize.predicate.enable", i1 true}