aboutsummaryrefslogtreecommitdiff
path: root/files/source/cpu_id.cc
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-27 10:16:29 -0700
committerXin Li <delphij@google.com>2020-08-27 10:16:29 -0700
commit4d17d097be332673859253f40601c4370affd7ad (patch)
treea584d2288d20f844a8e8ff89c875dbf7ce5278af /files/source/cpu_id.cc
parent179ebc697e2f9972f2fe7bd8d8f20c94ed334ccd (diff)
parent658fa7f244ce053b34a19b343b4ceb9bcacc20ec (diff)
downloadlibyuv-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.cc155
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