static void getAvailableFeatures()

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;
}