in lib/llvm/Support/Host.cpp [864:970]
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *FeaturesOut,
unsigned *Features2Out) {
unsigned Features = 0;
unsigned Features2 = 0;
unsigned EAX = 0, EBX = 0;
if ((EDX >> 15) & 1)
Features |= 1 << X86::FEATURE_CMOV;
if ((EDX >> 23) & 1)
Features |= 1 << X86::FEATURE_MMX;
if ((EDX >> 25) & 1)
Features |= 1 << X86::FEATURE_SSE;
if ((EDX >> 26) & 1)
Features |= 1 << X86::FEATURE_SSE2;
if ((ECX >> 0) & 1)
Features |= 1 << X86::FEATURE_SSE3;
if ((ECX >> 1) & 1)
Features |= 1 << X86::FEATURE_PCLMUL;
if ((ECX >> 9) & 1)
Features |= 1 << X86::FEATURE_SSSE3;
if ((ECX >> 12) & 1)
Features |= 1 << X86::FEATURE_FMA;
if ((ECX >> 19) & 1)
Features |= 1 << X86::FEATURE_SSE4_1;
if ((ECX >> 20) & 1)
Features |= 1 << X86::FEATURE_SSE4_2;
if ((ECX >> 23) & 1)
Features |= 1 << X86::FEATURE_POPCNT;
if ((ECX >> 25) & 1)
Features |= 1 << X86::FEATURE_AES;
if ((ECX >> 22) & 1)
Features2 |= 1 << (X86::FEATURE_MOVBE - 32);
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
// switch, then we have full AVX support.
const unsigned AVXBits = (1 << 27) | (1 << 28);
bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
((EAX & 0x6) == 0x6);
bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
if (HasAVX)
Features |= 1 << X86::FEATURE_AVX;
bool HasLeaf7 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7 && ((EBX >> 3) & 1))
Features |= 1 << X86::FEATURE_BMI;
if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
Features |= 1 << X86::FEATURE_AVX2;
if (HasLeaf7 && ((EBX >> 9) & 1))
Features |= 1 << X86::FEATURE_BMI2;
if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512F;
if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512DQ;
if (HasLeaf7 && ((EBX >> 19) & 1))
Features2 |= 1 << (X86::FEATURE_ADX - 32);
if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512IFMA;
if (HasLeaf7 && ((EBX >> 23) & 1))
Features2 |= 1 << (X86::FEATURE_CLFLUSHOPT - 32);
if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512PF;
if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512ER;
if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512CD;
if (HasLeaf7 && ((EBX >> 29) & 1))
Features2 |= 1 << (X86::FEATURE_SHA - 32);
if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512BW;
if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512VL;
if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512VBMI;
if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX512VPOPCNTDQ;
if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX5124VNNIW;
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
Features |= 1 << X86::FEATURE_AVX5124FMAPS;
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
if (HasExtLeaf1 && ((ECX >> 6) & 1))
Features |= 1 << X86::FEATURE_SSE4_A;
if (HasExtLeaf1 && ((ECX >> 11) & 1))
Features |= 1 << X86::FEATURE_XOP;
if (HasExtLeaf1 && ((ECX >> 16) & 1))
Features |= 1 << X86::FEATURE_FMA4;
if (HasExtLeaf1 && ((EDX >> 29) & 1))
Features2 |= 1 << (X86::FEATURE_EM64T - 32);
*FeaturesOut = Features;
*Features2Out = Features2;
}