]> git.uio.no Git - u/mrichter/AliRoot.git/blob - Vc/include/Vc/avx/vectorhelper.tcc
update to Vc 0.7.3-dev
[u/mrichter/AliRoot.git] / Vc / include / Vc / avx / vectorhelper.tcc
1 /*  This file is part of the Vc library.
2
3     Copyright (C) 2009-2011 Matthias Kretz <kretz@kde.org>
4
5     Vc is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as
7     published by the Free Software Foundation, either version 3 of
8     the License, or (at your option) any later version.
9
10     Vc is distributed in the hope that it will be useful, but
11     WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with Vc.  If not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20 #include "casts.h"
21 #include <cstdlib>
22
23 namespace AliRoot {
24 namespace Vc
25 {
26 namespace AVX
27 {
28
29 ////////////////////////////////////////////////////////////////////////////////////////////////////
30 // float_v
31 ////////////////////////////////////////////////////////////////////////////////////////////////////
32 //// loads
33 template<> Vc_ALWAYS_INLINE Vc_PURE m256 VectorHelper<m256>::load(const float *m, AlignedFlag)
34 {
35     return _mm256_load_ps(m);
36 }
37 template<> Vc_ALWAYS_INLINE Vc_PURE m256 VectorHelper<m256>::load(const float *m, UnalignedFlag)
38 {
39     return _mm256_loadu_ps(m);
40 }
41 template<> Vc_ALWAYS_INLINE Vc_PURE m256 VectorHelper<m256>::load(const float *m, StreamingAndAlignedFlag)
42 {
43     return avx_cast<m256>(concat(_mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<float *>(m))),
44                 _mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<float *>(&m[4])))));
45 }
46 template<> Vc_ALWAYS_INLINE Vc_PURE m256
47     VC_WARN("AVX does not support streaming unaligned loads. Will use non-streaming unaligned load instead.")
48 VectorHelper<m256>::load(const float *m, StreamingAndUnalignedFlag)
49 {
50     return _mm256_loadu_ps(m);
51 }
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53 //// stores
54 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, AlignedFlag)
55 {
56     _mm256_store_ps(mem, x);
57 }
58 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, UnalignedFlag)
59 {
60     _mm256_storeu_ps(mem, x);
61 }
62 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, StreamingAndAlignedFlag)
63 {
64     _mm256_stream_ps(mem, x);
65 }
66 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, StreamingAndUnalignedFlag)
67 {
68     _mm_maskmoveu_si128(avx_cast<m128i>(x), _mm_setallone_si128(), reinterpret_cast<char *>(mem));
69     _mm_maskmoveu_si128(_mm256_extractf128_si256(avx_cast<m256i>(x), 1), _mm_setallone_si128(), reinterpret_cast<char *>(mem + 4));
70 }
71 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, VTArg m, AlignedFlag)
72 {
73     _mm256_maskstore(mem, m, x);
74 }
75 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, VTArg m, UnalignedFlag)
76 {
77     _mm256_maskstore(mem, m, x);
78 }
79 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, VTArg m, StreamingAndAlignedFlag)
80 {
81     _mm_maskmoveu_si128(avx_cast<m128i>(x), avx_cast<m128i>(m), reinterpret_cast<char *>(mem));
82     _mm_maskmoveu_si128(_mm256_extractf128_si256(avx_cast<m256i>(x), 1), _mm256_extractf128_si256(avx_cast<m256i>(m), 1), reinterpret_cast<char *>(mem + 4));
83 }
84 Vc_ALWAYS_INLINE void VectorHelper<m256>::store(float *mem, VTArg x, VTArg m, StreamingAndUnalignedFlag)
85 {
86     _mm_maskmoveu_si128(avx_cast<m128i>(x), avx_cast<m128i>(m), reinterpret_cast<char *>(mem));
87     _mm_maskmoveu_si128(_mm256_extractf128_si256(avx_cast<m256i>(x), 1), _mm256_extractf128_si256(avx_cast<m256i>(m), 1), reinterpret_cast<char *>(mem + 4));
88 }
89
90 ////////////////////////////////////////////////////////////////////////////////////////////////////
91 // double_v
92 ////////////////////////////////////////////////////////////////////////////////////////////////////
93 //// loads
94 template<> Vc_ALWAYS_INLINE Vc_PURE m256d VectorHelper<m256d>::load(const double *m, AlignedFlag)
95 {
96     return _mm256_load_pd(m);
97 }
98 template<> Vc_ALWAYS_INLINE Vc_PURE m256d VectorHelper<m256d>::load(const double *m, UnalignedFlag)
99 {
100     return _mm256_loadu_pd(m);
101 }
102 template<> Vc_ALWAYS_INLINE Vc_PURE m256d VectorHelper<m256d>::load(const double *m, StreamingAndAlignedFlag)
103 {
104     return avx_cast<m256d>(concat(
105                 _mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<double *>(m))),
106                 _mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<double *>(&m[2])))));
107 }
108 template<> Vc_ALWAYS_INLINE Vc_PURE m256d
109     VC_WARN("AVX does not support streaming unaligned loads. Will use non-streaming unaligned load instead.")
110 VectorHelper<m256d>::load(const double *m, StreamingAndUnalignedFlag)
111 {
112     return _mm256_loadu_pd(m);
113 }
114 ////////////////////////////////////////////////////////////////////////////////////////////////////
115 //// stores
116 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, AlignedFlag)
117 {
118     _mm256_store_pd(mem, x);
119 }
120 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, UnalignedFlag)
121 {
122     _mm256_storeu_pd(mem, x);
123 }
124 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, StreamingAndAlignedFlag)
125 {
126     _mm256_stream_pd(mem, x);
127 }
128 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, StreamingAndUnalignedFlag)
129 {
130     _mm_maskmoveu_si128(avx_cast<m128i>(x), _mm_setallone_si128(), reinterpret_cast<char *>(mem));
131     _mm_maskmoveu_si128(avx_cast<m128i>(_mm256_extractf128_pd(x, 1)), _mm_setallone_si128(), reinterpret_cast<char *>(mem + 2));
132 }
133 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, VTArg m, AlignedFlag)
134 {
135     _mm256_maskstore(mem, m, x);
136 }
137 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, VTArg m, UnalignedFlag)
138 {
139     _mm256_maskstore(mem, m, x);
140 }
141 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, VTArg m, StreamingAndAlignedFlag)
142 {
143     _mm_maskmoveu_si128(avx_cast<m128i>(x), avx_cast<m128i>(m), reinterpret_cast<char *>(mem));
144     _mm_maskmoveu_si128(avx_cast<m128i>(_mm256_extractf128_pd(x, 1)), avx_cast<m128i>(_mm256_extractf128_pd(m, 1)), reinterpret_cast<char *>(mem + 2));
145 }
146 Vc_ALWAYS_INLINE void VectorHelper<m256d>::store(double *mem, VTArg x, VTArg m, StreamingAndUnalignedFlag)
147 {
148     _mm_maskmoveu_si128(avx_cast<m128i>(x), avx_cast<m128i>(m), reinterpret_cast<char *>(mem));
149     _mm_maskmoveu_si128(avx_cast<m128i>(_mm256_extractf128_pd(x, 1)), avx_cast<m128i>(_mm256_extractf128_pd(m, 1)), reinterpret_cast<char *>(mem + 2));
150 }
151 ////////////////////////////////////////////////////////////////////////////////////////////////////
152 // (u)int_v
153 ////////////////////////////////////////////////////////////////////////////////////////////////////
154 //// loads
155 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m256i VectorHelper<m256i>::load(const T *m, AlignedFlag)
156 {
157     return _mm256_load_si256(reinterpret_cast<const __m256i *>(m));
158 }
159 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m256i VectorHelper<m256i>::load(const T *m, UnalignedFlag)
160 {
161     return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(m));
162 }
163 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m256i VectorHelper<m256i>::load(const T *m, StreamingAndAlignedFlag)
164 {
165     return concat(_mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<T *>(m))),
166             _mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<T *>(&m[4]))));
167 }
168 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m256i
169     VC_WARN("AVX does not support streaming unaligned loads. Will use non-streaming unaligned load instead.")
170 VectorHelper<m256i>::load(const T *m, StreamingAndUnalignedFlag)
171 {
172     return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(m));
173 }
174 ////////////////////////////////////////////////////////////////////////////////////////////////////
175 //// stores
176 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, AlignedFlag)
177 {
178     _mm256_store_si256(reinterpret_cast<__m256i *>(mem), x);
179 }
180 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, UnalignedFlag)
181 {
182     _mm256_storeu_si256(reinterpret_cast<__m256i *>(mem), x);
183 }
184 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, StreamingAndAlignedFlag)
185 {
186     _mm256_stream_si256(reinterpret_cast<__m256i *>(mem), x);
187 }
188 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, StreamingAndUnalignedFlag)
189 {
190     _mm_maskmoveu_si128(avx_cast<m128i>(x), _mm_setallone_si128(), reinterpret_cast<char *>(mem));
191     _mm_maskmoveu_si128(_mm256_extractf128_si256(x, 1), _mm_setallone_si128(), reinterpret_cast<char *>(mem + 4));
192 }
193 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, VTArg m, AlignedFlag)
194 {
195     _mm256_maskstore(mem, m, x);
196 }
197 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, VTArg m, UnalignedFlag)
198 {
199     _mm256_maskstore(mem, m, x);
200 }
201 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, VTArg m, StreamingAndAlignedFlag)
202 {
203     _mm_maskmoveu_si128(lo128(x), lo128(m), reinterpret_cast<char *>(mem));
204     _mm_maskmoveu_si128(hi128(x), hi128(m), reinterpret_cast<char *>(mem + 4));
205 }
206 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m256i>::store(T *mem, VTArg x, VTArg m, StreamingAndUnalignedFlag)
207 {
208     _mm_maskmoveu_si128(lo128(x), lo128(m), reinterpret_cast<char *>(mem));
209     _mm_maskmoveu_si128(hi128(x), hi128(m), reinterpret_cast<char *>(mem + 4));
210 }
211 ////////////////////////////////////////////////////////////////////////////////////////////////////
212 // (u)short_v
213 ////////////////////////////////////////////////////////////////////////////////////////////////////
214 //// loads
215 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m128i VectorHelper<m128i>::load(const T *m, AlignedFlag)
216 {
217     return _mm_load_si128(reinterpret_cast<const __m128i *>(m));
218 }
219 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m128i VectorHelper<m128i>::load(const T *m, UnalignedFlag)
220 {
221     return _mm_loadu_si128(reinterpret_cast<const __m128i *>(m));
222 }
223 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m128i VectorHelper<m128i>::load(const T *m, StreamingAndAlignedFlag)
224 {
225     return _mm_stream_load_si128(reinterpret_cast<__m128i *>(const_cast<T *>(m)));
226 }
227 template<typename T> Vc_ALWAYS_INLINE Vc_PURE m128i
228     VC_WARN("AVX does not support streaming unaligned loads. Will use non-streaming unaligned load instead.")
229 VectorHelper<m128i>::load(const T *m, StreamingAndUnalignedFlag)
230 {
231     return _mm_loadu_si128(reinterpret_cast<const __m128i *>(m));
232 }
233 ////////////////////////////////////////////////////////////////////////////////////////////////////
234 //// stores
235 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, AlignedFlag)
236 {
237     _mm_store_si128(reinterpret_cast<__m128i *>(mem), x);
238 }
239 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, UnalignedFlag)
240 {
241     _mm_storeu_si128(reinterpret_cast<__m128i *>(mem), x);
242 }
243 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, StreamingAndAlignedFlag)
244 {
245     _mm_stream_si128(reinterpret_cast<__m128i *>(mem), x);
246 }
247 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, StreamingAndUnalignedFlag)
248 {
249     _mm_maskmoveu_si128(x, _mm_setallone_si128(), reinterpret_cast<char *>(mem));
250 }
251 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, VTArg m, AlignedFlag align)
252 {
253     store(mem, _mm_blendv_epi8(load(mem, align), x, m), align);
254 }
255 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, VTArg m, UnalignedFlag align)
256 {
257     store(mem, _mm_blendv_epi8(load(mem, align), x, m), align);
258 }
259 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, VTArg m, StreamingAndAlignedFlag)
260 {
261     _mm_maskmoveu_si128(x, m, reinterpret_cast<char *>(mem));
262 }
263 template<typename T> Vc_ALWAYS_INLINE void VectorHelper<m128i>::store(T *mem, VTArg x, VTArg m, StreamingAndUnalignedFlag)
264 {
265     _mm_maskmoveu_si128(x, m, reinterpret_cast<char *>(mem));
266 }
267
268 } // namespace AVX
269 } // namespace Vc
270 } // namespace AliRoot