diff options
author | Xin Li <delphij@google.com> | 2020-08-27 10:16:29 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2020-08-27 10:16:29 -0700 |
commit | 4d17d097be332673859253f40601c4370affd7ad (patch) | |
tree | a584d2288d20f844a8e8ff89c875dbf7ce5278af /files/source/cpu_id.cc | |
parent | 179ebc697e2f9972f2fe7bd8d8f20c94ed334ccd (diff) | |
parent | 658fa7f244ce053b34a19b343b4ceb9bcacc20ec (diff) | |
download | libyuv-4d17d097be332673859253f40601c4370affd7ad.tar.gz |
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)temp_sam_168057903
Bug: 166295507
Merged-In: I14d7f590626ed952689da92e72b4f0be8fff752f
Change-Id: I8f8254a06d6b6fdb726dbe8bcc162ef5a99fc546
Diffstat (limited to 'files/source/cpu_id.cc')
-rw-r--r-- | files/source/cpu_id.cc | 155 |
1 files changed, 54 insertions, 101 deletions
diff --git a/files/source/cpu_id.cc b/files/source/cpu_id.cc index afb5d282..48e2b615 100644 --- a/files/source/cpu_id.cc +++ b/files/source/cpu_id.cc @@ -19,16 +19,10 @@ #include <immintrin.h> // For _xgetbv() #endif -#if !defined(__native_client__) -#include <stdlib.h> // For getenv() -#endif - // For ArmCpuCaps() but unittested on all platforms #include <stdio.h> #include <string.h> -#include "libyuv/basic_types.h" // For CPU_X86 - #ifdef __cplusplus namespace libyuv { extern "C" { @@ -43,16 +37,20 @@ extern "C" { #define SAFEBUFFERS #endif +// cpu_info_ variable for SIMD instruction sets detected. +LIBYUV_API int cpu_info_ = 0; + +// TODO(fbarchard): Consider using int for cpuid so casting is not needed. // Low level cpuid for X86. #if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ defined(__x86_64__)) && \ !defined(__pnacl__) && !defined(__CLR_VER) LIBYUV_API -void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { +void CpuId(int info_eax, int info_ecx, int* cpu_info) { #if defined(_MSC_VER) // Visual C version uses intrinsic or inline x86 assembly. #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) - __cpuidex((int*)(cpu_info), info_eax, info_ecx); + __cpuidex(cpu_info, info_eax, info_ecx); #elif defined(_M_IX86) __asm { mov eax, info_eax @@ -66,14 +64,14 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { } #else // Visual C but not x86 if (info_ecx == 0) { - __cpuid((int*)(cpu_info), info_eax); + __cpuid(cpu_info, info_eax); } else { cpu_info[3] = cpu_info[2] = cpu_info[1] = cpu_info[0] = 0u; } #endif // GCC version uses inline x86 assembly. #else // defined(_MSC_VER) - uint32 info_ebx, info_edx; + int info_ebx, info_edx; asm volatile( #if defined(__i386__) && defined(__PIC__) // Preserve ebx for fpic 32 bit. @@ -94,7 +92,7 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { } #else // (defined(_M_IX86) || defined(_M_X64) ... LIBYUV_API -void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info) { +void CpuId(int eax, int ecx, int* cpu_info) { (void)eax; (void)ecx; cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; @@ -118,9 +116,9 @@ void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info) { !defined(__pnacl__) && !defined(__CLR_VER) && !defined(__native_client__) // X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. int GetXCR0() { - uint32 xcr0 = 0u; + int xcr0 = 0; #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) - xcr0 = (uint32)(_xgetbv(0)); // VS2010 SP1 required. + xcr0 = (int)_xgetbv(0); // VS2010 SP1 required. NOLINT #elif defined(__i386__) || defined(__x86_64__) asm(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr0) : "c"(0) : "%edx"); #endif // defined(__i386__) || defined(__x86_64__) @@ -154,7 +152,7 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { } // aarch64 uses asimd for Neon. p = strstr(cpuinfo_line, " asimd"); - if (p && (p[6] == ' ' || p[6] == '\n')) { + if (p) { fclose(f); return kCpuHasNEON; } @@ -164,27 +162,40 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { return 0; } +// TODO(fbarchard): Consider read_msa_ir(). +// TODO(fbarchard): Add unittest. LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name, const char ase[]) { char cpuinfo_line[512]; - int len = (int)strlen(ase); FILE* f = fopen(cpuinfo_name, "r"); if (!f) { // ase enabled if /proc/cpuinfo is unavailable. if (strcmp(ase, " msa") == 0) { return kCpuHasMSA; } - return kCpuHasDSPR2; + if (strcmp(ase, " mmi") == 0) { + return kCpuHasMMI; + } + return 0; } while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) { if (memcmp(cpuinfo_line, "ASEs implemented", 16) == 0) { char* p = strstr(cpuinfo_line, ase); - if (p && (p[len] == ' ' || p[len] == '\n')) { + if (p) { fclose(f); if (strcmp(ase, " msa") == 0) { return kCpuHasMSA; } - return kCpuHasDSPR2; + return 0; + } + } else if (memcmp(cpuinfo_line, "cpu model", 9) == 0) { + char* p = strstr(cpuinfo_line, "Loongson-3"); + if (p) { + fclose(f); + if (strcmp(ase, " mmi") == 0) { + return kCpuHasMMI; + } + return 0; } } } @@ -192,35 +203,14 @@ LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name, return 0; } -// CPU detect function for SIMD instruction sets. -LIBYUV_API -int cpu_info_ = 0; // cpu_info is not initialized yet. - -// Test environment variable for disabling CPU features. Any non-zero value -// to disable. Zero ignored to make it easy to set the variable on/off. -#if !defined(__native_client__) && !defined(_M_ARM) - -static LIBYUV_BOOL TestEnv(const char* name) { - const char* var = getenv(name); - if (var) { - if (var[0] != '0') { - return LIBYUV_TRUE; - } - } - return LIBYUV_FALSE; -} -#else // nacl does not support getenv(). -static LIBYUV_BOOL TestEnv(const char*) { - return LIBYUV_FALSE; -} -#endif - -LIBYUV_API SAFEBUFFERS int InitCpuFlags(void) { +static SAFEBUFFERS int GetCpuFlags(void) { int cpu_info = 0; -#if !defined(__pnacl__) && !defined(__CLR_VER) && defined(CPU_X86) - uint32 cpu_info0[4] = {0, 0, 0, 0}; - uint32 cpu_info1[4] = {0, 0, 0, 0}; - uint32 cpu_info7[4] = {0, 0, 0, 0}; +#if !defined(__pnacl__) && !defined(__CLR_VER) && \ + (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ + defined(_M_IX86)) + int cpu_info0[4] = {0, 0, 0, 0}; + int cpu_info1[4] = {0, 0, 0, 0}; + int cpu_info7[4] = {0, 0, 0, 0}; CpuId(0, 0, cpu_info0); CpuId(1, 0, cpu_info1); if (cpu_info0[0] >= 7) { @@ -241,60 +231,23 @@ LIBYUV_API SAFEBUFFERS int InitCpuFlags(void) { // Detect AVX512bw if ((GetXCR0() & 0xe0) == 0xe0) { - cpu_info |= (cpu_info7[1] & 0x40000000) ? kCpuHasAVX3 : 0; + cpu_info |= (cpu_info7[1] & 0x40000000) ? kCpuHasAVX512BW : 0; + cpu_info |= (cpu_info7[1] & 0x80000000) ? kCpuHasAVX512VL : 0; + cpu_info |= (cpu_info7[2] & 0x00000002) ? kCpuHasAVX512VBMI : 0; + cpu_info |= (cpu_info7[2] & 0x00000040) ? kCpuHasAVX512VBMI2 : 0; + cpu_info |= (cpu_info7[2] & 0x00001000) ? kCpuHasAVX512VBITALG : 0; + cpu_info |= (cpu_info7[2] & 0x00004000) ? kCpuHasAVX512VPOPCNTDQ : 0; + cpu_info |= (cpu_info7[2] & 0x00000100) ? kCpuHasGFNI : 0; } } - - // Environment variable overrides for testing. - if (TestEnv("LIBYUV_DISABLE_X86")) { - cpu_info &= ~kCpuHasX86; - } - if (TestEnv("LIBYUV_DISABLE_SSE2")) { - cpu_info &= ~kCpuHasSSE2; - } - if (TestEnv("LIBYUV_DISABLE_SSSE3")) { - cpu_info &= ~kCpuHasSSSE3; - } - if (TestEnv("LIBYUV_DISABLE_SSE41")) { - cpu_info &= ~kCpuHasSSE41; - } - if (TestEnv("LIBYUV_DISABLE_SSE42")) { - cpu_info &= ~kCpuHasSSE42; - } - if (TestEnv("LIBYUV_DISABLE_AVX")) { - cpu_info &= ~kCpuHasAVX; - } - if (TestEnv("LIBYUV_DISABLE_AVX2")) { - cpu_info &= ~kCpuHasAVX2; - } - if (TestEnv("LIBYUV_DISABLE_ERMS")) { - cpu_info &= ~kCpuHasERMS; - } - if (TestEnv("LIBYUV_DISABLE_FMA3")) { - cpu_info &= ~kCpuHasFMA3; - } - if (TestEnv("LIBYUV_DISABLE_AVX3")) { - cpu_info &= ~kCpuHasAVX3; - } - if (TestEnv("LIBYUV_DISABLE_F16C")) { - cpu_info &= ~kCpuHasF16C; - } - #endif #if defined(__mips__) && defined(__linux__) -#if defined(__mips_dspr2) - cpu_info |= kCpuHasDSPR2; -#endif #if defined(__mips_msa) cpu_info = MipsCpuCaps("/proc/cpuinfo", " msa"); +#elif defined(_MIPS_ARCH_LOONGSON3A) + cpu_info = MipsCpuCaps("/proc/cpuinfo", " mmi"); #endif cpu_info |= kCpuHasMIPS; - if (getenv("LIBYUV_DISABLE_DSPR2")) { - cpu_info &= ~kCpuHasDSPR2; - } - if (getenv("LIBYUV_DISABLE_MSA")) { - cpu_info &= ~kCpuHasMSA; - } #endif #if defined(__arm__) || defined(__aarch64__) // gcc -mfpu=neon defines __ARM_NEON__ @@ -313,22 +266,22 @@ LIBYUV_API SAFEBUFFERS int InitCpuFlags(void) { cpu_info = ArmCpuCaps("/proc/cpuinfo"); #endif cpu_info |= kCpuHasARM; - if (TestEnv("LIBYUV_DISABLE_NEON")) { - cpu_info &= ~kCpuHasNEON; - } #endif // __arm__ - if (TestEnv("LIBYUV_DISABLE_ASM")) { - cpu_info = 0; - } cpu_info |= kCpuInitialized; - cpu_info_ = cpu_info; return cpu_info; } // Note that use of this function is not thread safe. LIBYUV_API -void MaskCpuFlags(int enable_flags) { - cpu_info_ = InitCpuFlags() & enable_flags; +int MaskCpuFlags(int enable_flags) { + int cpu_info = GetCpuFlags() & enable_flags; + SetCpuFlags(cpu_info); + return cpu_info; +} + +LIBYUV_API +int InitCpuFlags(void) { + return MaskCpuFlags(-1); } #ifdef __cplusplus |