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