How to check if the processor supports the SSE3 instruction set?

Is the following code valid for checking if the processor supports the SSE3 instruction set?

Using the IsProcessorFeaturePresent() function does not seem to work on Windows XP (see http://msdn.microsoft.com/en-us/library/ms724482(v=vs.85).aspx ).

 bool CheckSSE3() { int CPUInfo[4] = {-1}; //-- Get number of valid info ids __cpuid(CPUInfo, 0); int nIds = CPUInfo[0]; //-- Get info for id "1" if (nIds >= 1) { __cpuid(CPUInfo, 1); bool bSSE3NewInstructions = (CPUInfo[2] & 0x1) || false; return bSSE3NewInstructions; } return false; } 
+58
c ++ sse avx instruction-set cpuid
May 25 '11 at 8:49
source share
5 answers

I created a GitHub registry that will detect CPU and OS support for all major ISA x86 extensions: https://github.com/Mysticial/FeatureDetector

Here is a shorter version:




First you need to access the CPUID instruction:

 #ifdef _WIN32 // Windows #define cpuid(info, x) __cpuidex(info, x, 0) #else // GCC Intrinsics #include <cpuid.h> void cpuid(int info[4], int InfoType){ __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]); } #endif 

Then you can run the following code:

 // Misc. bool HW_MMX; bool HW_x64; bool HW_ABM; // Advanced Bit Manipulation bool HW_RDRAND; bool HW_BMI1; bool HW_BMI2; bool HW_ADX; bool HW_PREFETCHWT1; // SIMD: 128-bit bool HW_SSE; bool HW_SSE2; bool HW_SSE3; bool HW_SSSE3; bool HW_SSE41; bool HW_SSE42; bool HW_SSE4a; bool HW_AES; bool HW_SHA; // SIMD: 256-bit bool HW_AVX; bool HW_XOP; bool HW_FMA3; bool HW_FMA4; bool HW_AVX2; // SIMD: 512-bit bool HW_AVX512F; // AVX512 Foundation bool HW_AVX512CD; // AVX512 Conflict Detection bool HW_AVX512PF; // AVX512 Prefetch bool HW_AVX512ER; // AVX512 Exponential + Reciprocal bool HW_AVX512VL; // AVX512 Vector Length Extensions bool HW_AVX512BW; // AVX512 Byte + Word bool HW_AVX512DQ; // AVX512 Doubleword + Quadword bool HW_AVX512IFMA; // AVX512 Integer 52-bit Fused Multiply-Add bool HW_AVX512VBMI; // AVX512 Vector Byte Manipulation Instructions int info[4]; cpuid(info, 0); int nIds = info[0]; cpuid(info, 0x80000000); unsigned nExIds = info[0]; // Detect Features if (nIds >= 0x00000001){ cpuid(info,0x00000001); HW_MMX = (info[3] & ((int)1 << 23)) != 0; HW_SSE = (info[3] & ((int)1 << 25)) != 0; HW_SSE2 = (info[3] & ((int)1 << 26)) != 0; HW_SSE3 = (info[2] & ((int)1 << 0)) != 0; HW_SSSE3 = (info[2] & ((int)1 << 9)) != 0; HW_SSE41 = (info[2] & ((int)1 << 19)) != 0; HW_SSE42 = (info[2] & ((int)1 << 20)) != 0; HW_AES = (info[2] & ((int)1 << 25)) != 0; HW_AVX = (info[2] & ((int)1 << 28)) != 0; HW_FMA3 = (info[2] & ((int)1 << 12)) != 0; HW_RDRAND = (info[2] & ((int)1 << 30)) != 0; } if (nIds >= 0x00000007){ cpuid(info,0x00000007); HW_AVX2 = (info[1] & ((int)1 << 5)) != 0; HW_BMI1 = (info[1] & ((int)1 << 3)) != 0; HW_BMI2 = (info[1] & ((int)1 << 8)) != 0; HW_ADX = (info[1] & ((int)1 << 19)) != 0; HW_SHA = (info[1] & ((int)1 << 29)) != 0; HW_PREFETCHWT1 = (info[2] & ((int)1 << 0)) != 0; HW_AVX512F = (info[1] & ((int)1 << 16)) != 0; HW_AVX512CD = (info[1] & ((int)1 << 28)) != 0; HW_AVX512PF = (info[1] & ((int)1 << 26)) != 0; HW_AVX512ER = (info[1] & ((int)1 << 27)) != 0; HW_AVX512VL = (info[1] & ((int)1 << 31)) != 0; HW_AVX512BW = (info[1] & ((int)1 << 30)) != 0; HW_AVX512DQ = (info[1] & ((int)1 << 17)) != 0; HW_AVX512IFMA = (info[1] & ((int)1 << 21)) != 0; HW_AVX512VBMI = (info[2] & ((int)1 << 1)) != 0; } if (nExIds >= 0x80000001){ cpuid(info,0x80000001); HW_x64 = (info[3] & ((int)1 << 29)) != 0; HW_ABM = (info[2] & ((int)1 << 5)) != 0; HW_SSE4a = (info[2] & ((int)1 << 6)) != 0; HW_FMA4 = (info[2] & ((int)1 << 16)) != 0; HW_XOP = (info[2] & ((int)1 << 11)) != 0; } 



Note that this only determines if the processor supports instructions. To run them, you will also need operating system support.

In particular, operating system support is required for:

  • x64. (You need a 64-bit OS.)
  • Instructions that use (AVX) 256-bit ymm registers. See Andy Lutomirsky ’s answer on how to detect this.
  • Instructions that use 512-bit zmm registers and a mask (AVX512). OS support detection for the AVX512 is the same as for the AVX, but using the 0xe6 flag instead of 0x6 .
+85
Sep 21 2018-11-11T00:
source share

The mystical answer is a little dangerous - it explains how to determine CPU support, but not support the OS. You need to use _xgetbv to check if the OS has activated the required extended CPU state. See here for another source. Even gcc made the same mistake. Ball Code:

 bool avxSupported = false; int cpuInfo[4]; __cpuid(cpuInfo, 1); bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false; bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false; if (osUsesXSAVE_XRSTORE && cpuAVXSuport) { unsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); avxSupported = (xcrFeatureMask & 0x6) == 0x6; } 
+46
Mar 20 '14 at 1:22
source share

After a brief search, I also found solutions from Intel:

Link: https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family

  void cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd) { #if defined(_MSC_VER) __cpuidex((int*)abcd, eax, ecx); #else uint32_t ebx, edx; # if defined( __i386__ ) && defined ( __PIC__ ) /* in case of PIC under 32-bit EBX cannot be clobbered */ __asm__("movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx), # else __asm__("cpuid" : "+b" (ebx), # endif "+a" (eax), "+c" (ecx), "=d" (edx)); abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx; #endif } int check_xcr0_ymm() { uint32_t xcr0; #if defined(_MSC_VER) xcr0 = (uint32_t)_xgetbv(0); /* min VS2010 SP1 compiler is required */ #else __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); #endif return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */ } 

Also note that there are some special built-in functions in GCC that you can use (see: https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/X86-Built-in-Functions.html ):

  if (__builtin_cpu_supports("avx2")) // ... 

If you put this together with the information above, everything will be fine.

+8
Feb 10 '15 at 20:53
source share

On Mac OS, this works:

 sysctl -a | grep machdep.cpu.features 

In my machine, this outputs this:

machdep. .1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C

As you can see from the instructions in bold, SSE3 and a bunch of other SIMD instructions are supported.

+3
Mar 03 '18 at 1:01
source share

To add the answer to Abhiroop: On linux, you can run this shell command to find out the features supported by your processor.

cat/proc/cpuinfo | grep flags | uniq

It prints on my machine

flags: FPU VME de pseudoephedrine TSC MSR pae MCE CX8 APIC SEP MTRR PGE MCA CMOV pat pse36 clflush MMX fxsr cse sse2 XT system call px pdpe1gb rdtscp lm constant_tsc repcfqfpfpfpfpfpfpfpfperpfperpfperpfperpfperpfperpfer POPCNT tsc_deadline_timer AEC xsave avx f16c hypervisor rdrand lahf_lm abm 3dnowprefetch invpcid_single retpoline kaiser fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx xsaveopt

+1
Mar 26 '18 at 19:51
source share



All Articles