Skip to content

Instantly share code, notes, and snippets.

@lh3
Created September 5, 2017 17:06
Show Gist options
  • Save lh3/3fd977099883e866857b9d3718a680b1 to your computer and use it in GitHub Desktop.
Save lh3/3fd977099883e866857b9d3718a680b1 to your computer and use it in GitHub Desktop.
Get supported SIMD instruction sets (x86 only)
#include <stdio.h>
#define SIMD_SSE 0x1
#define SIMD_SSE2 0x2
#define SIMD_SSE3 0x4
#define SIMD_SSSE3 0x8
#define SIMD_SSE4_1 0x10
#define SIMD_SSE4_2 0x20
#define SIMD_AVX 0x40
#define SIMD_AVX2 0x80
#define SIMD_AVX512F 0x100
#ifndef _MSC_VER
// adapted from https://github.com/01org/linux-sgx/blob/master/common/inc/internal/linux/cpuid_gnu.h
void __cpuidex(int cpuid[4], int func_id, int subfunc_id)
{
#if defined(__x86_64__)
asm volatile ("cpuid"
: "=a" (cpuid[0]), "=b" (cpuid[1]), "=c" (cpuid[2]), "=d" (cpuid[3])
: "0" (func_id), "2" (subfunc_id));
#else // on 32bit, ebx can NOT be used as PIC code
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
: "=a" (cpuid[0]), "=r" (cpuid[1]), "=c" (cpuid[2]), "=d" (cpuid[3])
: "0" (func_id), "2" (subfunc_id));
#endif
}
#endif
int x86_simd(void)
{
int flag = 0, cpuid[4], max_id;
__cpuidex(cpuid, 0, 0);
max_id = cpuid[0];
if (max_id == 0) return 0;
__cpuidex(cpuid, 1, 0);
if (cpuid[3]>>25&1) flag |= SIMD_SSE;
if (cpuid[3]>>26&1) flag |= SIMD_SSE2;
if (cpuid[2]>>0 &1) flag |= SIMD_SSE3;
if (cpuid[2]>>9 &1) flag |= SIMD_SSSE3;
if (cpuid[2]>>19&1) flag |= SIMD_SSE4_1;
if (cpuid[2]>>20&1) flag |= SIMD_SSE4_2;
if (cpuid[2]>>28&1) flag |= SIMD_AVX;
if (max_id >= 7) {
__cpuidex(cpuid, 7, 0);
if (cpuid[1]>>5 &1) flag |= SIMD_AVX2;
if (cpuid[1]>>16&1) flag |= SIMD_AVX512F;
}
return flag;
}
const char *simd_name[9] = { "sse", "sse2", "sse3", "ssse3", "sse4.1", "sse4.2", "avx", "avx2", "avx512f" };
int main()
{
unsigned i, simd_flag;
simd_flag = x86_simd();
for (i = 0; i < 8; ++i)
if (simd_flag>>i&1) puts(simd_name[i]);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment