58b3d267266aba2bca288593a61491363a76567c
[blender-staging.git] / intern / cycles / util / util_simd.h
1 /*
2  * Copyright 2011-2013 Intel Corporation
3  * Modifications Copyright 2014, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0(the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef __UTIL_SIMD_TYPES_H__
19 #define __UTIL_SIMD_TYPES_H__
20
21 #ifndef __KERNEL_GPU__
22
23 #include <limits>
24
25 #include "util/util_debug.h"
26 #include "util/util_defines.h"
27
28 /* SSE Intrinsics includes
29  *
30  * We assume __KERNEL_SSEX__ flags to have been defined at this point */
31
32 /* SSE intrinsics headers */
33 #ifndef FREE_WINDOWS64
34
35 #ifdef _MSC_VER
36 #  include <intrin.h>
37 #elif (defined(__x86_64__) || defined(__i386__))
38 #  include <x86intrin.h>
39 #endif
40
41 #else
42
43 /* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
44  * Since we can't avoid including <windows.h>, better only include that */
45 #include "util/util_windows.h"
46
47 #endif
48
49 CCL_NAMESPACE_BEGIN
50
51 #ifdef __KERNEL_SSE2__
52
53 extern const __m128 _mm_lookupmask_ps[16];
54
55 /* Special Types */
56
57 static struct TrueTy {
58 __forceinline operator bool( ) const { return true; }
59 } True ccl_maybe_unused;
60
61 static struct FalseTy {
62 __forceinline operator bool( ) const { return false; }
63 } False ccl_maybe_unused;
64
65 static struct NegInfTy
66 {
67 __forceinline operator          float    ( ) const { return -std::numeric_limits<float>::infinity(); }
68 __forceinline operator          int      ( ) const { return std::numeric_limits<int>::min(); }
69 } neg_inf ccl_maybe_unused;
70
71 static struct PosInfTy
72 {
73 __forceinline operator          float    ( ) const { return std::numeric_limits<float>::infinity(); }
74 __forceinline operator          int      ( ) const { return std::numeric_limits<int>::max(); }
75 } inf ccl_maybe_unused, pos_inf ccl_maybe_unused;
76
77 /* Intrinsics Functions */
78
79 #if defined(__BMI__) && defined(__GNUC__)
80 #  ifndef _tzcnt_u32
81 #    define _tzcnt_u32 __tzcnt_u32
82 #  endif
83 #  ifndef _tzcnt_u64
84 #    define _tzcnt_u64 __tzcnt_u64
85 #  endif
86 #endif
87
88 #if defined(__LZCNT__)
89 #define _lzcnt_u32 __lzcnt32
90 #define _lzcnt_u64 __lzcnt64
91 #endif
92
93 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__clang__)
94
95 __forceinline int __popcnt(int in) {
96   return _mm_popcnt_u32(in);
97 }
98
99 #if !defined(_MSC_VER)
100 __forceinline unsigned int __popcnt(unsigned int in) {
101   return _mm_popcnt_u32(in);
102 }
103 #endif
104
105 #if defined(__KERNEL_64_BIT__)
106 __forceinline long long __popcnt(long long in) {
107   return _mm_popcnt_u64(in);
108 }
109 __forceinline size_t __popcnt(size_t in) {
110   return _mm_popcnt_u64(in);
111 }
112 #endif
113
114 __forceinline int __bsf(int v) {
115 #if defined(__KERNEL_AVX2__) 
116   return _tzcnt_u32(v);
117 #else
118   unsigned long r = 0; _BitScanForward(&r,v); return r;
119 #endif
120 }
121
122 __forceinline unsigned int __bsf(unsigned int v) {
123 #if defined(__KERNEL_AVX2__) 
124   return _tzcnt_u32(v);
125 #else
126   unsigned long r = 0; _BitScanForward(&r,v); return r;
127 #endif
128 }
129
130 __forceinline int __bsr(int v) {
131   unsigned long r = 0; _BitScanReverse(&r,v); return r;
132 }
133
134 __forceinline int __btc(int v, int i) {
135   long r = v; _bittestandcomplement(&r,i); return r;
136 }
137
138 __forceinline int __bts(int v, int i) {
139   long r = v; _bittestandset(&r,i); return r;
140 }
141
142 __forceinline int __btr(int v, int i) {
143   long r = v; _bittestandreset(&r,i); return r;
144 }
145
146 __forceinline int bitscan(int v) {
147 #if defined(__KERNEL_AVX2__) 
148   return _tzcnt_u32(v);
149 #else
150   return __bsf(v);
151 #endif
152 }
153
154 __forceinline int clz(const int x)
155 {
156 #if defined(__KERNEL_AVX2__)
157   return _lzcnt_u32(x);
158 #else
159   if(UNLIKELY(x == 0)) return 32;
160   return 31 - __bsr(x);    
161 #endif
162 }
163
164 __forceinline int __bscf(int& v) 
165 {
166   int i = __bsf(v);
167   v &= v-1;
168   return i;
169 }
170
171 __forceinline unsigned int __bscf(unsigned int& v) 
172 {
173   unsigned int i = __bsf(v);
174   v &= v-1;
175   return i;
176 }
177
178 #if defined(__KERNEL_64_BIT__)
179
180 __forceinline size_t __bsf(size_t v) {
181 #if defined(__KERNEL_AVX2__) 
182   return _tzcnt_u64(v);
183 #else
184   unsigned long r = 0; _BitScanForward64(&r,v); return r;
185 #endif
186 }
187
188 __forceinline size_t __bsr(size_t v) {
189   unsigned long r = 0; _BitScanReverse64(&r,v); return r;
190 }
191
192 __forceinline size_t __btc(size_t v, size_t i) {
193   size_t r = v; _bittestandcomplement64((__int64*)&r,i); return r;
194 }
195
196 __forceinline size_t __bts(size_t v, size_t i) {
197   __int64 r = v; _bittestandset64(&r,i); return r;
198 }
199
200 __forceinline size_t __btr(size_t v, size_t i) {
201   __int64 r = v; _bittestandreset64(&r,i); return r;
202 }
203
204 __forceinline size_t bitscan(size_t v) {
205 #if defined(__KERNEL_AVX2__)
206 #if defined(__KERNEL_64_BIT__)
207   return _tzcnt_u64(v);
208 #else
209   return _tzcnt_u32(v);
210 #endif
211 #else
212   return __bsf(v);
213 #endif
214 }
215
216 __forceinline size_t __bscf(size_t& v) 
217 {
218   size_t i = __bsf(v);
219   v &= v-1;
220   return i;
221 }
222
223 #endif /* __KERNEL_64_BIT__ */
224
225 #else /* _WIN32 */
226
227 __forceinline unsigned int __popcnt(unsigned int in) {
228   int r = 0; asm ("popcnt %1,%0" : "=r"(r) : "r"(in)); return r;
229 }
230
231 __forceinline int __bsf(int v) {
232   int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
233 }
234
235 __forceinline int __bsr(int v) {
236   int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
237 }
238
239 __forceinline int __btc(int v, int i) {
240   int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
241 }
242
243 __forceinline int __bts(int v, int i) {
244   int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
245 }
246
247 __forceinline int __btr(int v, int i) {
248   int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
249 }
250
251 #if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
252 __forceinline size_t __bsf(size_t v) {
253   size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
254 }
255 #endif
256
257 __forceinline unsigned int __bsf(unsigned int v) {
258   unsigned int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
259 }
260
261 __forceinline size_t __bsr(size_t v) {
262   size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
263 }
264
265 __forceinline size_t __btc(size_t v, size_t i) {
266   size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
267 }
268
269 __forceinline size_t __bts(size_t v, size_t i) {
270   size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
271 }
272
273 __forceinline size_t __btr(size_t v, size_t i) {
274   size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
275 }
276
277 __forceinline int bitscan(int v) {
278 #if defined(__KERNEL_AVX2__) 
279   return _tzcnt_u32(v);
280 #else
281   return __bsf(v);
282 #endif
283 }
284
285 __forceinline unsigned int bitscan(unsigned int v) {
286 #if defined(__KERNEL_AVX2__) 
287   return _tzcnt_u32(v);
288 #else
289   return __bsf(v);
290 #endif
291 }
292
293 #if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
294 __forceinline size_t bitscan(size_t v) {
295 #if defined(__KERNEL_AVX2__)
296 #if defined(__KERNEL_64_BIT__)
297   return _tzcnt_u64(v);
298 #else
299   return _tzcnt_u32(v);
300 #endif
301 #else
302   return __bsf(v);
303 #endif
304 }
305 #endif
306
307 __forceinline int clz(const int x)
308 {
309 #if defined(__KERNEL_AVX2__)
310   return _lzcnt_u32(x);
311 #else
312   if(UNLIKELY(x == 0)) return 32;
313   return 31 - __bsr(x);    
314 #endif
315 }
316
317 __forceinline int __bscf(int& v) 
318 {
319   int i = bitscan(v);
320 #if defined(__KERNEL_AVX2__)
321   v &= v-1;
322 #else
323   v = __btc(v,i);
324 #endif
325   return i;
326 }
327
328 __forceinline unsigned int __bscf(unsigned int& v) 
329 {
330   unsigned int i = bitscan(v);
331   v &= v-1;
332   return i;
333 }
334
335 #if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
336 __forceinline size_t __bscf(size_t& v) 
337 {
338   size_t i = bitscan(v);
339 #if defined(__KERNEL_AVX2__)
340   v &= v-1;
341 #else
342   v = __btc(v,i);
343 #endif
344   return i;
345 }
346 #endif
347
348 #endif /* _WIN32 */
349
350 /* Test __KERNEL_SSE41__ for MSVC which does not define __SSE4_1__, and test
351  * __SSE4_1__ to avoid OpenImageIO conflicts with our emulation macros on other
352  * platforms when compiling code outside the kernel. */
353 #if !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__))
354
355 /* Emulation of SSE4 functions with SSE2 */
356
357 #define _MM_FROUND_TO_NEAREST_INT    0x00
358 #define _MM_FROUND_TO_NEG_INF        0x01
359 #define _MM_FROUND_TO_POS_INF        0x02
360 #define _MM_FROUND_TO_ZERO           0x03
361 #define _MM_FROUND_CUR_DIRECTION     0x04
362
363 #undef _mm_blendv_ps
364 #define _mm_blendv_ps _mm_blendv_ps_emu
365 __forceinline __m128 _mm_blendv_ps_emu( __m128 value, __m128 input, __m128 mask)
366 {
367     __m128i isignmask = _mm_set1_epi32(0x80000000);
368     __m128 signmask = _mm_castsi128_ps(isignmask);
369     __m128i iandsign = _mm_castps_si128(_mm_and_ps(mask, signmask));
370     __m128i icmpmask = _mm_cmpeq_epi32(iandsign, isignmask);
371     __m128 cmpmask = _mm_castsi128_ps(icmpmask);
372     return _mm_or_ps(_mm_and_ps(cmpmask, input), _mm_andnot_ps(cmpmask, value));
373 }
374
375 #undef _mm_blend_ps
376 #define _mm_blend_ps _mm_blend_ps_emu
377 __forceinline __m128 _mm_blend_ps_emu( __m128 value, __m128 input, const int mask)
378 {
379     assert(mask < 0x10); return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]); 
380 }
381
382 #undef _mm_blendv_epi8
383 #define _mm_blendv_epi8 _mm_blendv_epi8_emu
384 __forceinline __m128i _mm_blendv_epi8_emu( __m128i value, __m128i input, __m128i mask)
385 {
386     return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value)); 
387 }
388
389 #undef _mm_min_epi32
390 #define _mm_min_epi32 _mm_min_epi32_emu
391 __forceinline __m128i _mm_min_epi32_emu( __m128i value, __m128i input)
392 {
393     return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input)); 
394 }
395
396 #undef _mm_max_epi32
397 #define _mm_max_epi32 _mm_max_epi32_emu
398 __forceinline __m128i _mm_max_epi32_emu( __m128i value, __m128i input)
399 {
400     return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input)); 
401 }
402
403 #undef _mm_extract_epi32
404 #define _mm_extract_epi32 _mm_extract_epi32_emu
405 __forceinline int _mm_extract_epi32_emu( __m128i input, const int index)
406 {
407   switch(index) {
408   case 0: return _mm_cvtsi128_si32(input);
409   case 1: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
410   case 2: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
411   case 3: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(3, 3, 3, 3)));
412   default: assert(false); return 0;
413   }
414 }
415
416 #undef _mm_insert_epi32
417 #define _mm_insert_epi32 _mm_insert_epi32_emu
418 __forceinline __m128i _mm_insert_epi32_emu( __m128i value, int input, const int index)
419 {
420     assert(index >= 0 && index < 4); ((int*)&value)[index] = input; return value; 
421 }
422
423 #undef _mm_insert_ps
424 #define _mm_insert_ps _mm_insert_ps_emu
425 __forceinline __m128 _mm_insert_ps_emu( __m128 value, __m128 input, const int index)
426 {
427         assert(index < 0x100);
428         ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6];
429         return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value);
430 }
431
432 #undef _mm_round_ps
433 #define _mm_round_ps _mm_round_ps_emu
434 __forceinline __m128 _mm_round_ps_emu( __m128 value, const int flags)
435 {
436   switch(flags)
437   {
438   case _MM_FROUND_TO_NEAREST_INT: return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
439   case _MM_FROUND_TO_NEG_INF    : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
440   case _MM_FROUND_TO_POS_INF    : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps( 0.5f))));
441   case _MM_FROUND_TO_ZERO       : return _mm_cvtepi32_ps(_mm_cvttps_epi32(value));
442   }
443   return value;
444 }
445
446 #endif /* !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__)) */
447
448 #else  /* __KERNEL_SSE2__ */
449
450 /* This section is for utility functions which operates on non-register data
451  * which might be used from a non-vectorized code.
452  */
453
454 ccl_device_inline int bitscan(int value)
455 {
456         assert(value != 0);
457         int bit = 0;
458         while(value >>= 1) {
459                 ++bit;
460         }
461         return bit;
462 }
463
464
465 #endif /* __KERNEL_SSE2__ */
466
467 /* quiet unused define warnings */
468 #if defined(__KERNEL_SSE2__)  || \
469         defined(__KERNEL_SSE3__)  || \
470         defined(__KERNEL_SSSE3__) || \
471         defined(__KERNEL_SSE41__) || \
472         defined(__KERNEL_AVX__)   || \
473         defined(__KERNEL_AVX2__)
474         /* do nothing */
475 #endif
476
477 CCL_NAMESPACE_END
478
479 #endif /* __KERNEL_GPU__ */
480
481 #endif /* __UTIL_SIMD_TYPES_H__ */
482