diff --git a/include/libyuv/cpu_id.h b/include/libyuv/cpu_id.h index 61a934ce2..c6983fb32 100644 --- a/include/libyuv/cpu_id.h +++ b/include/libyuv/cpu_id.h @@ -60,6 +60,7 @@ static const int kCpuHasAVX10_2 = 0x2000000; static const int kCpuHasAVXVNNI = 0x4000000; static const int kCpuHasAVXVNNIINT8 = 0x8000000; static const int kCpuHasAMXINT8 = 0x10000000; +static const int kCpuHasAVX512BMM = 0x20000000; // These flags are only valid on LOONGARCH processors. static const int kCpuHasLOONGARCH = 0x20; diff --git a/source/cpu_id.cc b/source/cpu_id.cc index 0d7ea9a95..0cc46b10a 100644 --- a/source/cpu_id.cc +++ b/source/cpu_id.cc @@ -397,6 +397,7 @@ static SAFEBUFFERS int GetCpuFlags(void) { int cpu_info7[4] = {0, 0, 0, 0}; int cpu_einfo7[4] = {0, 0, 0, 0}; int cpu_info24[4] = {0, 0, 0, 0}; + int cpu_info21[4] = {0, 0, 0, 0}; int cpu_amdinfo21[4] = {0, 0, 0, 0}; CpuId(0, 0, cpu_info0); CpuId(1, 0, cpu_info1); @@ -405,6 +406,9 @@ static SAFEBUFFERS int GetCpuFlags(void) { CpuId(7, 1, cpu_einfo7); CpuId(0x80000021, 0, cpu_amdinfo21); } + if (cpu_info0[0] >= 0x21) { + CpuId(0x21, 0, cpu_info21); + } if (cpu_info0[0] >= 0x24) { CpuId(0x24, 0, cpu_info24); } @@ -435,7 +439,8 @@ static SAFEBUFFERS int GetCpuFlags(void) { ((cpu_info7[2] & 0x00000800) ? kCpuHasAVX512VNNI : 0) | ((cpu_info7[2] & 0x00001000) ? kCpuHasAVX512VBITALG : 0) | ((cpu_einfo7[3] & 0x00080000) ? kCpuHasAVX10 : 0) | - ((cpu_info7[3] & 0x02000000) ? kCpuHasAMXINT8 : 0); + ((cpu_info7[3] & 0x02000000) ? kCpuHasAMXINT8 : 0) | + ((cpu_info21[0] & 0x00800000) ? kCpuHasAVX512BMM : 0); if (cpu_info0[0] >= 0x24 && (cpu_einfo7[3] & 0x00080000)) { cpu_info |= ((cpu_info24[1] & 0xFF) >= 2) ? kCpuHasAVX10_2 : 0; } diff --git a/unit_test/cpu_test.cc b/unit_test/cpu_test.cc index b24f3e250..b249e70df 100644 --- a/unit_test/cpu_test.cc +++ b/unit_test/cpu_test.cc @@ -189,6 +189,7 @@ TEST_F(LibYUVBaseTest, TestCpuHas) { int has_avxvnni = TestCpuFlag(kCpuHasAVXVNNI); int has_avxvnniint8 = TestCpuFlag(kCpuHasAVXVNNIINT8); int has_amxint8 = TestCpuFlag(kCpuHasAMXINT8); + int has_avx512bmm = TestCpuFlag(kCpuHasAVX512BMM); printf("Has X86 0x%x\n", has_x86); printf("Has SSE2 0x%x\n", has_sse2); printf("Has SSSE3 0x%x\n", has_ssse3); @@ -211,6 +212,7 @@ TEST_F(LibYUVBaseTest, TestCpuHas) { printf("HAS AVXVNNI 0x%x\n", has_avxvnni); printf("Has AVXVNNIINT8 0x%x\n", has_avxvnniint8); printf("Has AMXINT8 0x%x\n", has_amxint8); + printf("Has AVX512BMM 0x%x\n", has_avx512bmm); } #endif // defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || // defined(_M_X64) diff --git a/util/cpuid.c b/util/cpuid.c index 38b2c0e9d..bbaea8398 100644 --- a/util/cpuid.c +++ b/util/cpuid.c @@ -15,6 +15,8 @@ #ifdef __linux__ #include #include +#include +#include #endif #include "libyuv/cpu_id.h" @@ -40,6 +42,14 @@ static void KernelVersion(int* version) { } #endif +#ifdef __linux__ +static sigjmp_buf vdpphps_jmpbuf; +static void vdpphps_sigill_handler(int sig) { + (void)sig; + siglongjmp(vdpphps_jmpbuf, 1); +} +#endif + int main(int argc, const char* argv[]) { (void)argc; (void)argv; @@ -182,6 +192,7 @@ int main(int argc, const char* argv[]) { int has_avxvnni = TestCpuFlag(kCpuHasAVXVNNI); int has_avxvnniint8 = TestCpuFlag(kCpuHasAVXVNNIINT8); int has_amxint8 = TestCpuFlag(kCpuHasAMXINT8); + int has_avx512bmm = TestCpuFlag(kCpuHasAVX512BMM); printf("Has X86 0x%x\n", has_x86); printf("Has SSE2 0x%x\n", has_sse2); printf("Has SSSE3 0x%x\n", has_ssse3); @@ -204,6 +215,30 @@ int main(int argc, const char* argv[]) { printf("HAS AVXVNNI 0x%x\n", has_avxvnni); printf("Has AVXVNNIINT8 0x%x\n", has_avxvnniint8); printf("Has AMXINT8 0x%x\n", has_amxint8); + printf("Has AVX512BMM 0x%x\n", has_avx512bmm); + +#ifdef __linux__ + // Test VDPPHPS instruction + { + struct sigaction act, oldact; + memset(&act, 0, sizeof(act)); + act.sa_handler = vdpphps_sigill_handler; + sigaction(SIGILL, &act, &oldact); + + printf("Testing VDPPHPS instruction... "); + fflush(stdout); + + if (sigsetjmp(vdpphps_jmpbuf, 1) == 0) { + // VDPPHPS xmm0, xmm0, xmm0 + __asm__ volatile("vdpphps %%xmm0, %%xmm0, %%xmm0" : : : "xmm0"); + printf("Works!\n"); + } else { + printf("Crashed (SIGILL)!\n"); + } + + sigaction(SIGILL, &oldact, NULL); + } +#endif } #endif // defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || // defined(_M_X64)