1 /*****************************************************************************/
2 // Copyright 2017-2019 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
6 // accordance with the terms of the Adobe license agreement accompanying it.
7 /*****************************************************************************/
8 
9 #ifndef __dng_simd_type__
10 #define __dng_simd_type__
11 
12 /*****************************************************************************/
13 
14 #include "dng_flags.h"
15 
16 /*****************************************************************************/
17 
18 #if qDNGIntelCompiler
19 #include <immintrin.h>
20 #endif	// qDNGIntelCompiler
21 
22 /*****************************************************************************/
23 
24 enum SIMDType
25 	{
26 
27 	Scalar,
28 
29 	SSE2,       // Pentium 4
30 	AVX,        // Sandy Bridge
31 	AVX2,       // Haswell
32 	F16C = AVX2, //Ivy bridge
33 	AVX512_SKX, // Sky Lake Server
34 
35 	SIMD_Sentinel
36 
37 	};
38 
39 /*****************************************************************************/
40 
41 template <int SIMDType>
42 class SIMDTraits
43 {
44 public:
45 	static const int kVecSizeFloat = 1;
46 	static const int kVecSizeInt32 = 1;
47 };
48 
49 template <>
50 class SIMDTraits<SSE2>
51 {
52 public:
53 	static const int kVecSizeFloat = 4;
54 	static const int kVecSizeInt32 = 4;
55 };
56 
57 template <>
58 class SIMDTraits<AVX>
59 {
60 public:
61 	static const int kVecSizeFloat = 8;
62 	static const int kVecSizeInt32 = 4;
63 };
64 
65 template <>
66 class SIMDTraits<AVX2>
67 {
68 public:
69 	static const int kVecSizeFloat = 8;
70 	static const int kVecSizeInt32 = 8;
71 };
72 
73 template <>
74 class SIMDTraits<AVX512_SKX>
75 {
76 public:
77 	static const int kVecSizeFloat = 16;
78 	static const int kVecSizeInt32 = 16;
79 };
80 
81 const SIMDType SIMDTypeMaxValue = SIMDType(SIMD_Sentinel - 1);
82 
83 extern SIMDType	gDNGMaxSIMD;
84 
85 /*****************************************************************************/
86 
87 #if qDNGIntelCompiler
88 
89 // Intel compiler.
90 
91 // Macros are preferred for "#pragma simd" because at some point these will
92 // all change to OpenMP 4.x compliant "#pragma omp simd" directives (no longer
93 // Intel-specific).
94 //
95 // Note that _Pragma(x) requires C99 or C++11 support.
96 
97 // Pre-defined feature levels.
98 
99 #define CR_SIMD_MIN_FEATURE   (_FEATURE_SSE2)
100 #define CR_AVX_FEATURE        (_FEATURE_AVX)
101 #define CR_AVX2_FEATURE       (_FEATURE_AVX|_FEATURE_FMA|_FEATURE_AVX2)
102 #define CR_F16C_FEATURE			CR_AVX2_FEATURE
103 #define CR_AVX512_SKX_FEATURE (_FEATURE_AVX512F|_FEATURE_AVX512CD|_FEATURE_AVX512BW|_FEATURE_AVX512DQ|_FEATURE_AVX512VL)
104 #define CR_COMPILER_USING_AVX512_SKX (__AVX512F__ && __AVX512VL__ && __AVX512BW__ && __AVX512DQ__ && __AVX512CD__)
105 
106 #define __SIMDTYPE_TFY(x) #x
107 #define _SIMDTYPE_TFY(x) __SIMDTYPE_TFY(x)
108 
109 #if qDNGDebug
110 
111 // Debug build.
112 
113 //#define INTEL_PRAGMA_SIMD_ASSERT_C(clause) _Pragma(PM2__STR1__(simd clause))
114 #define INTEL_PRAGMA_SIMD_ASSERT _Pragma("simd")
115 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_FLOAT(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeFloat ) ))
116 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT32(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32 ) ))
117 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT16(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32*2 ) ))
118 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT8(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32*4 ) ))
119 
120 #else
121 
122 // Release build.
123 
124 //#define INTEL_PRAGMA_SIMD_ASSERT_C(clause) _Pragma(PM2__STR1__(simd assert clause))
125 #define INTEL_PRAGMA_SIMD_ASSERT _Pragma("simd assert")
126 #if 1
127 #if (__INTEL_COMPILER < 1800)
128 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_FLOAT(s) _Pragma(_SIMDTYPE_TFY(simd assert vectorlength( SIMDTraits<s>::kVecSizeFloat ) ))
129 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT32(s) _Pragma(_SIMDTYPE_TFY(simd assert vectorlength( SIMDTraits<s>::kVecSizeInt32 ) ))
130 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT16(s) _Pragma(_SIMDTYPE_TFY(simd assert vectorlength( SIMDTraits<s>::kVecSizeInt32*2 ) ))
131 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT8(s) _Pragma(_SIMDTYPE_TFY(simd assert vectorlength( SIMDTraits<s>::kVecSizeInt32*4 ) ))
132 #else
133 // FIX_ME_ERIC_CHAN: I removed the assert to fix compile time error when using Intel compiler version 18.
134 // Need to figure out correct fix when we switch to newer version. - tknoll 10/30/2017.
135 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_FLOAT(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeFloat ) ))
136 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT32(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32 ) ))
137 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT16(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32*2 ) ))
138 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT8(s) _Pragma(_SIMDTYPE_TFY(simd vectorlength( SIMDTraits<s>::kVecSizeInt32*4 ) ))
139 #endif
140 #else
141 // Don't force
142 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_FLOAT(s) _Pragma(_SIMDTYPE_TFY(simd assert))
143 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT32(s) _Pragma(_SIMDTYPE_TFY(simd assert))
144 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT16(s) _Pragma(_SIMDTYPE_TFY(simd assert))
145 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT8(s) _Pragma(_SIMDTYPE_TFY(simd assert))
146 #endif
147 #endif
148 
149 #define SET_CPU_FEATURE(simd) _allow_cpu_features( (simd >= AVX512_SKX) ? CR_AVX512_SKX_FEATURE : (simd >= AVX2) ? CR_AVX2_FEATURE : ((simd >= AVX) ? CR_AVX_FEATURE : CR_SIMD_MIN_FEATURE) )
150 //#define SET_CPU_FEATURE_NOFMA(simd) _allow_cpu_features( ((simd >= AVX512_SKX) ? CR_AVX512_SKX_FEATURE : (simd >= AVX2) ? CR_AVX2_FEATURE : ((simd >= AVX) ? CR_AVX_FEATURE : CR_SIMD_MIN_FEATURE)) & ~_FEATURE_FMA )
151 #define SET_CPU_FEATURE_NOFMA(simd) _allow_cpu_features( (simd >= AVX) ? CR_AVX_FEATURE : CR_SIMD_MIN_FEATURE)
152 #define INTEL_PRAGMA_NOVECTOR _Pragma("novector")
153 #define INTEL_COMPILER_NEEDED_NOTE
154 
155 #else
156 
157 // Non-Intel compiler. Use empty definitions for the macros.
158 // Credit: http://www.highprogrammer.com/alan/windev/visualstudio.html, but avoid using $ character
159 #define Stringize( L )			#L
160 #define MakeString( M, L )		M(L)
161 #define _x_Line					MakeString( Stringize, __LINE__ )
162 
163 #if qDNGValidateTarget
164 // Do not warn about Intel compiler if building dng_validate.
165 #define INTEL_COMPILER_NEEDED_NOTE
166 #else
167 #if !(defined (IOS_ENV) || defined(ANDROID_ENV)) && (defined(__x86_64__) || defined(__i386__))
168 #ifndef _MSC_VER
169 #define INTEL_COMPILER_NEEDED_NOTE _Pragma("message(\"NOTE: Intel Compiler needed for optimizations in \" __FILE__ \":\" _x_Line )")
170 #else
171 // Intel compiler understands C99 _Pragma, but not Microsoft, so use MS-specific __pragma instead
172 #define INTEL_COMPILER_NEEDED_NOTE __pragma(message("NOTE: Intel Compiler needed for optimizations in " __FILE__ ":" _x_Line " in " __FUNCTION__))
173 #endif
174 #else
175 #define INTEL_COMPILER_NEEDED_NOTE
176 #endif
177 #endif
178 
179 #define INTEL_PRAGMA_SIMD_ASSERT
180 //#define INTEL_PRAGMA_SIMD_ASSERT_C(clause)
181 #define SET_CPU_FEATURE(simd)
182 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_FLOAT(simd)
183 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT16(simd)
184 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT32(simd)
185 #define INTEL_PRAGMA_SIMD_ASSERT_VECLEN_INT8(simd)
186 #define INTEL_PRAGMA_NOVECTOR
187 
188 #endif	// qDNGIntelCompiler
189 
190 /*****************************************************************************/
191 
192 #endif	// __dng_simd_type__
193 
194 /*****************************************************************************/
195