Changeset 5633 for pjproject/trunk/third_party/yuv/source/cpu_id.cc
- Timestamp:
- Jul 28, 2017 2:51:44 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/third_party/yuv/source/cpu_id.cc
r5539 r5633 14 14 #include <intrin.h> // For __cpuidex() 15 15 #endif 16 #if !defined(__pnacl__) && !defined(__CLR_VER) && \16 #if !defined(__pnacl__) && !defined(__CLR_VER) && \ 17 17 !defined(__native_client__) && (defined(_M_IX86) || defined(_M_X64)) && \ 18 18 defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) … … 44 44 #endif 45 45 46 // cpu_info_ variable for SIMD instruction sets detected. 47 LIBYUV_API int cpu_info_ = 0; 48 49 // TODO(fbarchard): Consider using int for cpuid so casting is not needed. 46 50 // Low level cpuid for X86. 47 #if (defined(_M_IX86) || defined(_M_X64) || \48 defined(__i386__) || defined(__x86_64__)) &&\51 #if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ 52 defined(__x86_64__)) && \ 49 53 !defined(__pnacl__) && !defined(__CLR_VER) 50 54 LIBYUV_API 51 void CpuId( uint32 info_eax, uint32 info_ecx, uint32* cpu_info) {55 void CpuId(int info_eax, int info_ecx, int* cpu_info) { 52 56 #if defined(_MSC_VER) 53 57 // Visual C version uses intrinsic or inline x86 assembly. 54 58 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) 55 __cpuidex( (int*)(cpu_info), info_eax, info_ecx);59 __cpuidex(cpu_info, info_eax, info_ecx); 56 60 #elif defined(_M_IX86) 57 61 __asm { … … 67 71 #else // Visual C but not x86 68 72 if (info_ecx == 0) { 69 __cpuid( (int*)(cpu_info), info_eax);73 __cpuid(cpu_info, info_eax); 70 74 } else { 71 cpu_info[3] = cpu_info[2] = cpu_info[1] = cpu_info[0] = 0 ;75 cpu_info[3] = cpu_info[2] = cpu_info[1] = cpu_info[0] = 0u; 72 76 } 73 77 #endif 74 78 // GCC version uses inline x86 assembly. 75 79 #else // defined(_MSC_VER) 76 uint32info_ebx, info_edx;77 asm volatile 78 #if defined( 79 // Preserve ebx for fpic 32 bit.80 "mov %%ebx, %%edi \n"81 "cpuid \n"82 "xchg %%edi, %%ebx \n"83 : "=D"(info_ebx),84 #else 85 "cpuid \n"86 : "=b"(info_ebx),80 int info_ebx, info_edx; 81 asm volatile( 82 #if defined(__i386__) && defined(__PIC__) 83 // Preserve ebx for fpic 32 bit. 84 "mov %%ebx, %%edi \n" 85 "cpuid \n" 86 "xchg %%edi, %%ebx \n" 87 : "=D"(info_ebx), 88 #else 89 "cpuid \n" 90 : "=b"(info_ebx), 87 91 #endif // defined( __i386__) && defined(__PIC__) 88 "+a" (info_eax), "+c" (info_ecx), "=d"(info_edx));92 "+a"(info_eax), "+c"(info_ecx), "=d"(info_edx)); 89 93 cpu_info[0] = info_eax; 90 94 cpu_info[1] = info_ebx; … … 95 99 #else // (defined(_M_IX86) || defined(_M_X64) ... 96 100 LIBYUV_API 97 void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info) { 101 void CpuId(int eax, int ecx, int* cpu_info) { 102 (void)eax; 103 (void)ecx; 98 104 cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; 99 105 } … … 112 118 #pragma optimize("g", off) 113 119 #endif 114 #if (defined(_M_IX86) || defined(_M_X64) || \115 defined(__i386__) || defined(__x86_64__)) &&\120 #if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ 121 defined(__x86_64__)) && \ 116 122 !defined(__pnacl__) && !defined(__CLR_VER) && !defined(__native_client__) 117 #define HAS_XGETBV118 123 // X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. 119 124 int GetXCR0() { 120 uint32 xcr0 = 0u;125 int xcr0 = 0; 121 126 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) 122 xcr0 = (uint32)(_xgetbv(0)); // VS2010 SP1 required.127 xcr0 = _xgetbv(0); // VS2010 SP1 required. 123 128 #elif defined(__i386__) || defined(__x86_64__) 124 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcr0) : "c"(0) : "%edx");129 asm(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr0) : "c"(0) : "%edx"); 125 130 #endif // defined(__i386__) || defined(__x86_64__) 126 131 return xcr0; 127 132 } 133 #else 134 // xgetbv unavailable to query for OSSave support. Return 0. 135 #define GetXCR0() 0 128 136 #endif // defined(_M_IX86) || defined(_M_X64) .. 129 137 // Return optimization to previous setting. … … 134 142 // based on libvpx arm_cpudetect.c 135 143 // For Arm, but public to allow testing on any CPU 136 LIBYUV_API SAFEBUFFERS 137 int ArmCpuCaps(const char* cpuinfo_name) { 144 LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { 138 145 char cpuinfo_line[512]; 139 146 FILE* f = fopen(cpuinfo_name, "r"); … … 152 159 // aarch64 uses asimd for Neon. 153 160 p = strstr(cpuinfo_line, " asimd"); 154 if (p && (p[6] == ' ' || p[6] == '\n')) {161 if (p) { 155 162 fclose(f); 156 163 return kCpuHasNEON; … … 162 169 } 163 170 164 // CPU detect function for SIMD instruction sets. 165 LIBYUV_API 166 int cpu_info_ = 0; // cpu_info is not initialized yet. 171 // TODO(fbarchard): Consider read_msa_ir(). 172 // TODO(fbarchard): Add unittest. 173 LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name, 174 const char ase[]) { 175 char cpuinfo_line[512]; 176 FILE* f = fopen(cpuinfo_name, "r"); 177 if (!f) { 178 // ase enabled if /proc/cpuinfo is unavailable. 179 if (strcmp(ase, " msa") == 0) { 180 return kCpuHasMSA; 181 } 182 return kCpuHasDSPR2; 183 } 184 while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) { 185 if (memcmp(cpuinfo_line, "ASEs implemented", 16) == 0) { 186 char* p = strstr(cpuinfo_line, ase); 187 if (p) { 188 fclose(f); 189 if (strcmp(ase, " msa") == 0) { 190 return kCpuHasMSA; 191 } 192 return kCpuHasDSPR2; 193 } 194 } 195 } 196 fclose(f); 197 return 0; 198 } 167 199 168 200 // Test environment variable for disabling CPU features. Any non-zero value 169 201 // to disable. Zero ignored to make it easy to set the variable on/off. 170 #if !defined(__native_client__) && !defined(_M_ARM) && !defined(_MSC_VER)202 #if !defined(__native_client__) && !defined(_M_ARM) 171 203 172 204 static LIBYUV_BOOL TestEnv(const char* name) { … … 185 217 #endif 186 218 187 LIBYUV_API SAFEBUFFERS 188 int InitCpuFlags(void) { 189 // TODO(fbarchard): swap kCpuInit logic so 0 means uninitialized. 219 static SAFEBUFFERS int GetCpuFlags(void) { 190 220 int cpu_info = 0; 191 221 #if !defined(__pnacl__) && !defined(__CLR_VER) && defined(CPU_X86) 192 uint32 cpu_info0[4] = { 0, 0, 0, 0};193 uint32 cpu_info1[4] = { 0, 0, 0, 0};194 uint32 cpu_info7[4] = { 0, 0, 0, 0};222 int cpu_info0[4] = {0, 0, 0, 0}; 223 int cpu_info1[4] = {0, 0, 0, 0}; 224 int cpu_info7[4] = {0, 0, 0, 0}; 195 225 CpuId(0, 0, cpu_info0); 196 226 CpuId(1, 0, cpu_info1); … … 198 228 CpuId(7, 0, cpu_info7); 199 229 } 200 cpu_info = ((cpu_info1[3] & 0x04000000) ? kCpuHasSSE2 : 0) |230 cpu_info = kCpuHasX86 | ((cpu_info1[3] & 0x04000000) ? kCpuHasSSE2 : 0) | 201 231 ((cpu_info1[2] & 0x00000200) ? kCpuHasSSSE3 : 0) | 202 232 ((cpu_info1[2] & 0x00080000) ? kCpuHasSSE41 : 0) | 203 233 ((cpu_info1[2] & 0x00100000) ? kCpuHasSSE42 : 0) | 204 ((cpu_info7[1] & 0x00000200) ? kCpuHasERMS : 0) | 205 ((cpu_info1[2] & 0x00001000) ? kCpuHasFMA3 : 0) | 206 kCpuHasX86; 207 208 #ifdef HAS_XGETBV 209 // AVX requires CPU has AVX, XSAVE and OSXSave for xgetbv 234 ((cpu_info7[1] & 0x00000200) ? kCpuHasERMS : 0); 235 236 // AVX requires OS saves YMM registers. 210 237 if (((cpu_info1[2] & 0x1c000000) == 0x1c000000) && // AVX and OSXSave 211 238 ((GetXCR0() & 6) == 6)) { // Test OS saves YMM registers 212 cpu_info |= ((cpu_info7[1] & 0x00000020) ? kCpuHasAVX2 : 0) | kCpuHasAVX; 239 cpu_info |= kCpuHasAVX | ((cpu_info7[1] & 0x00000020) ? kCpuHasAVX2 : 0) | 240 ((cpu_info1[2] & 0x00001000) ? kCpuHasFMA3 : 0) | 241 ((cpu_info1[2] & 0x20000000) ? kCpuHasF16C : 0); 213 242 214 243 // Detect AVX512bw … … 217 246 } 218 247 } 219 #endif220 248 221 249 // Environment variable overrides for testing. … … 250 278 cpu_info &= ~kCpuHasAVX3; 251 279 } 280 if (TestEnv("LIBYUV_DISABLE_F16C")) { 281 cpu_info &= ~kCpuHasF16C; 282 } 283 252 284 #endif 253 285 #if defined(__mips__) && defined(__linux__) … … 255 287 cpu_info |= kCpuHasDSPR2; 256 288 #endif 289 #if defined(__mips_msa) 290 cpu_info = MipsCpuCaps("/proc/cpuinfo", " msa"); 291 #endif 257 292 cpu_info |= kCpuHasMIPS; 258 293 if (getenv("LIBYUV_DISABLE_DSPR2")) { 259 294 cpu_info &= ~kCpuHasDSPR2; 295 } 296 if (getenv("LIBYUV_DISABLE_MSA")) { 297 cpu_info &= ~kCpuHasMSA; 260 298 } 261 299 #endif … … 284 322 cpu_info = 0; 285 323 } 286 cpu_info |= kCpuInitialized; 287 cpu_info_ = cpu_info; 324 cpu_info |= kCpuInitialized; 288 325 return cpu_info; 289 326 } … … 291 328 // Note that use of this function is not thread safe. 292 329 LIBYUV_API 293 void MaskCpuFlags(int enable_flags) { 294 cpu_info_ = InitCpuFlags() & enable_flags; 330 int MaskCpuFlags(int enable_flags) { 331 int cpu_info = GetCpuFlags() & enable_flags; 332 #ifdef __ATOMIC_RELAXED 333 __atomic_store_n(&cpu_info_, cpu_info, __ATOMIC_RELAXED); 334 #else 335 cpu_info_ = cpu_info; 336 #endif 337 return cpu_info; 338 } 339 340 LIBYUV_API 341 int InitCpuFlags(void) { 342 return MaskCpuFlags(-1); 295 343 } 296 344
Note: See TracChangeset
for help on using the changeset viewer.