From 78070bc1ba0978000268f919f1138bede28df436 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Tue, 25 Sep 2012 19:13:04 +0000 Subject: [PATCH] Added CPUID change to detect AVX2. BUG=98 TEST=none Review URL: https://webrtc-codereview.appspot.com/839004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@373 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 18 +++++++++--------- include/libyuv/cpu_id.h | 2 +- include/libyuv/version.h | 2 +- source/cpu_id.cc | 30 ++++++++++++++++++++++++++++-- unit_test/cpu_test.cc | 2 ++ 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/README.chromium b/README.chromium index 9dc6f330e..0412b0daf 100644 --- a/README.chromium +++ b/README.chromium @@ -1,9 +1,9 @@ -Name: libyuv -URL: http://code.google.com/p/libyuv/ -Version: 372 -License: BSD -License File: LICENSE - -Description: -libyuv is an open source project that includes -YUV conversion and scaling functionality. +Name: libyuv +URL: http://code.google.com/p/libyuv/ +Version: 373 +License: BSD +License File: LICENSE + +Description: +libyuv is an open source project that includes +YUV conversion and scaling functionality. diff --git a/include/libyuv/cpu_id.h b/include/libyuv/cpu_id.h index e96438388..019329d2d 100644 --- a/include/libyuv/cpu_id.h +++ b/include/libyuv/cpu_id.h @@ -31,7 +31,7 @@ static const int kCpuHasSSSE3 = 0x40; static const int kCpuHasSSE41 = 0x80; static const int kCpuHasSSE42 = 0x100; static const int kCpuHasAVX = 0x200; -// 0x400 reserved for AVX2. +static const int kCpuHasAVX2 = 0x400; // Detect CPU has SSE2 etc. // Test_flag parameter should be one of kCpuHas constants above. diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 090bde592..b8fe8d8dd 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 372 +#define LIBYUV_VERSION 373 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/cpu_id.cc b/source/cpu_id.cc index fb307f045..61c2f93de 100644 --- a/source/cpu_id.cc +++ b/source/cpu_id.cc @@ -50,11 +50,25 @@ extern "C" { #if !defined(__CLR_VER) && (defined(_M_IX86) || defined(_M_X64) || \ defined(__i386__) || defined(__x86_64__)) void CpuId(int cpu_info[4], int info_type) { - __cpuid(cpu_info, info_type); + __cpuid(cpu_info, info_type); } #else void CpuId(int cpu_info[4], int) { - cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; +} +#endif + +// Low level cpuid for X86. Returns zeros on other CPUs. +#if !defined(__CLR_VER) && defined(_M_IX86) +// TODO(fbarchard): Port to GCC and 64 bit Visual C. +#define HAS_XGETBV +// Return low 32 bits of BV - OS support for register saving. +__declspec(naked) +static uint32 XGetBV32(void) { + _asm _emit 0x0f + _asm _emit 0x01 + _asm _emit 0xd0 // xgetbv + _asm ret } #endif @@ -91,8 +105,17 @@ int InitCpuFlags() { ((cpu_info[2] & 0x00000200) ? kCpuHasSSSE3 : 0) | ((cpu_info[2] & 0x00080000) ? kCpuHasSSE41 : 0) | ((cpu_info[2] & 0x00100000) ? kCpuHasSSE42 : 0) | + // TODO(fbarchard): AVX test BV same as AVX2. (((cpu_info[2] & 0x18000000) == 0x18000000) ? kCpuHasAVX : 0) | kCpuInitialized | kCpuHasX86; +#ifdef HAS_XGETBV + if (cpu_info_ & kCpuHasAVX) { + __cpuid(cpu_info, 7); + if ((cpu_info[1] & 0x00000020) && ((XGetBV32() & 0x06) == 0x06)) { + cpu_info_ |= kCpuHasAVX2; + } + } +#endif // environment variable overrides for testing. if (getenv("LIBYUV_DISABLE_X86")) { @@ -113,6 +136,9 @@ int InitCpuFlags() { if (getenv("LIBYUV_DISABLE_AVX")) { cpu_info_ &= ~kCpuHasAVX; } + if (getenv("LIBYUV_DISABLE_AVX2")) { + cpu_info_ &= ~kCpuHasAVX2; + } if (getenv("LIBYUV_DISABLE_ASM")) { cpu_info_ = kCpuInitialized; } diff --git a/unit_test/cpu_test.cc b/unit_test/cpu_test.cc index 5be4e0c21..fbf6da92a 100644 --- a/unit_test/cpu_test.cc +++ b/unit_test/cpu_test.cc @@ -37,6 +37,8 @@ TEST_F(libyuvTest, TestCpuHas) { printf("Has SSE4.2 %x\n", has_sse42); int has_avx = TestCpuFlag(kCpuHasAVX); printf("Has AVX %x\n", has_avx); + int has_avx2 = TestCpuFlag(kCpuHasAVX2); + printf("Has AVX2 %x\n", has_avx2); } #if defined(__i386__) || defined(__x86_64__) || \