[X86] Move frontend CPU feature initialization to a look up table based implementatio...
authorCraig Topper <craig.topper@intel.com>
Tue, 30 Jun 2020 18:59:03 +0000 (11:59 -0700)
committerCraig Topper <craig.topper@intel.com>
Tue, 30 Jun 2020 19:04:58 +0000 (12:04 -0700)
This replaces the switch statement implementation in the clang's
X86.cpp with a lookup table in X86TargetParser.cpp.

I've used constexpr and copy of the FeatureBitset from
SubtargetFeature.h to store the features in a lookup table.
After the lookup the bitset is translated into strings for use
by the rest of the frontend code.

I had to modify the implementation of the FeatureBitset to avoid
bugs in gcc 5.5 constexpr handling. It seems to not like the
same array entry to be used on the left side and right hand side
of an assignment or &= or |=. I've also used uint32_t instead of
uint64_t and sized based on the X86::CPU_FEATURE_MAX.

I've initialized the features for different CPUs outside of the
table so that we can express inheritance in an adhoc way. This
was one of the big limitations of the switch and we had resorted
to labels and gotos.

Differential Revision: https://reviews.llvm.org/D82731

clang/lib/Basic/Targets/X86.cpp
clang/lib/CodeGen/CGBuiltin.cpp
llvm/include/llvm/Support/X86TargetParser.def
llvm/include/llvm/Support/X86TargetParser.h
llvm/lib/Support/X86TargetParser.cpp

index 4b61f3c..30f4570 100644 (file)
@@ -110,342 +110,12 @@ bool X86TargetInfo::initFeatureMap(
     setFeatureEnabledImpl(Features, "sse2", true);
 
   using namespace llvm::X86;
-  const enum CPUKind Kind = parseArchX86(CPU);
 
-  // Enable X87 for all X86 processors but Lakemont.
-  if (Kind != CK_Lakemont)
-    setFeatureEnabledImpl(Features, "x87", true);
+  SmallVector<StringRef, 16> CPUFeatures;
+  getFeaturesForCPU(CPU, CPUFeatures);
+  for (auto &F : CPUFeatures)
+    setFeatureEnabledImpl(Features, F, true);
 
-  // Enable cmpxchg8 for i586 and greater CPUs. Include generic for backwards
-  // compatibility.
-  if (Kind >= CK_i586 || Kind == CK_None)
-    setFeatureEnabledImpl(Features, "cx8", true);
-
-  switch (Kind) {
-  case CK_None:
-  case CK_i386:
-  case CK_i486:
-  case CK_i586:
-  case CK_Pentium:
-  case CK_PentiumPro:
-  case CK_i686:
-  case CK_Lakemont:
-    break;
-
-  case CK_Cooperlake:
-    // CPX inherits all CLX features plus AVX512BF16
-    setFeatureEnabledImpl(Features, "avx512bf16", true);
-    LLVM_FALLTHROUGH;
-  case CK_Cascadelake:
-    // CLX inherits all SKX features plus AVX512VNNI
-    setFeatureEnabledImpl(Features, "avx512vnni", true);
-    LLVM_FALLTHROUGH;
-  case CK_SkylakeServer:
-    setFeatureEnabledImpl(Features, "avx512f", true);
-    setFeatureEnabledImpl(Features, "avx512cd", true);
-    setFeatureEnabledImpl(Features, "avx512dq", true);
-    setFeatureEnabledImpl(Features, "avx512bw", true);
-    setFeatureEnabledImpl(Features, "avx512vl", true);
-    setFeatureEnabledImpl(Features, "clwb", true);
-    setFeatureEnabledImpl(Features, "pku", true);
-    // SkylakeServer cores inherits all SKL features, except SGX
-    goto SkylakeCommon;
-
-  case CK_Tigerlake:
-    setFeatureEnabledImpl(Features, "avx512vp2intersect", true);
-    setFeatureEnabledImpl(Features, "movdiri", true);
-    setFeatureEnabledImpl(Features, "movdir64b", true);
-    setFeatureEnabledImpl(Features, "shstk", true);
-    // Tigerlake cores inherits IcelakeClient, except pconfig and wbnoinvd
-    goto IcelakeCommon;
-
-  case CK_IcelakeServer:
-    setFeatureEnabledImpl(Features, "pconfig", true);
-    setFeatureEnabledImpl(Features, "wbnoinvd", true);
-    LLVM_FALLTHROUGH;
-  case CK_IcelakeClient:
-IcelakeCommon:
-    setFeatureEnabledImpl(Features, "vaes", true);
-    setFeatureEnabledImpl(Features, "gfni", true);
-    setFeatureEnabledImpl(Features, "vpclmulqdq", true);
-    setFeatureEnabledImpl(Features, "avx512bitalg", true);
-    setFeatureEnabledImpl(Features, "avx512vbmi2", true);
-    setFeatureEnabledImpl(Features, "avx512vnni", true);
-    setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
-    setFeatureEnabledImpl(Features, "rdpid", true);
-    setFeatureEnabledImpl(Features, "clwb", true);
-    LLVM_FALLTHROUGH;
-  case CK_Cannonlake:
-    setFeatureEnabledImpl(Features, "avx512f", true);
-    setFeatureEnabledImpl(Features, "avx512cd", true);
-    setFeatureEnabledImpl(Features, "avx512dq", true);
-    setFeatureEnabledImpl(Features, "avx512bw", true);
-    setFeatureEnabledImpl(Features, "avx512vl", true);
-    setFeatureEnabledImpl(Features, "avx512ifma", true);
-    setFeatureEnabledImpl(Features, "avx512vbmi", true);
-    setFeatureEnabledImpl(Features, "pku", true);
-    setFeatureEnabledImpl(Features, "sha", true);
-    LLVM_FALLTHROUGH;
-  case CK_SkylakeClient:
-    setFeatureEnabledImpl(Features, "sgx", true);
-    // SkylakeServer cores inherits all SKL features, except SGX
-SkylakeCommon:
-    setFeatureEnabledImpl(Features, "xsavec", true);
-    setFeatureEnabledImpl(Features, "xsaves", true);
-    setFeatureEnabledImpl(Features, "clflushopt", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    LLVM_FALLTHROUGH;
-  case CK_Broadwell:
-    setFeatureEnabledImpl(Features, "rdseed", true);
-    setFeatureEnabledImpl(Features, "adx", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    LLVM_FALLTHROUGH;
-  case CK_Haswell:
-    setFeatureEnabledImpl(Features, "avx2", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "bmi", true);
-    setFeatureEnabledImpl(Features, "bmi2", true);
-    setFeatureEnabledImpl(Features, "fma", true);
-    setFeatureEnabledImpl(Features, "invpcid", true);
-    setFeatureEnabledImpl(Features, "movbe", true);
-    LLVM_FALLTHROUGH;
-  case CK_IvyBridge:
-    setFeatureEnabledImpl(Features, "rdrnd", true);
-    setFeatureEnabledImpl(Features, "f16c", true);
-    setFeatureEnabledImpl(Features, "fsgsbase", true);
-    LLVM_FALLTHROUGH;
-  case CK_SandyBridge:
-    setFeatureEnabledImpl(Features, "avx", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    LLVM_FALLTHROUGH;
-  case CK_Westmere:
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    LLVM_FALLTHROUGH;
-  case CK_Nehalem:
-    setFeatureEnabledImpl(Features, "sse4.2", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    LLVM_FALLTHROUGH;
-  case CK_Penryn:
-    setFeatureEnabledImpl(Features, "sse4.1", true);
-    LLVM_FALLTHROUGH;
-  case CK_Core2:
-    setFeatureEnabledImpl(Features, "ssse3", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    LLVM_FALLTHROUGH;
-  case CK_Nocona:
-    setFeatureEnabledImpl(Features, "cx16", true);
-    LLVM_FALLTHROUGH;
-  case CK_Yonah:
-  case CK_Prescott:
-    setFeatureEnabledImpl(Features, "sse3", true);
-    LLVM_FALLTHROUGH;
-  case CK_PentiumM:
-  case CK_Pentium4:
-  case CK_x86_64:
-    setFeatureEnabledImpl(Features, "sse2", true);
-    LLVM_FALLTHROUGH;
-  case CK_Pentium3:
-  case CK_C3_2:
-    setFeatureEnabledImpl(Features, "sse", true);
-    LLVM_FALLTHROUGH;
-  case CK_Pentium2:
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    LLVM_FALLTHROUGH;
-  case CK_PentiumMMX:
-  case CK_K6:
-  case CK_WinChipC6:
-    setFeatureEnabledImpl(Features, "mmx", true);
-    break;
-
-  case CK_Tremont:
-    setFeatureEnabledImpl(Features, "clwb", true);
-    setFeatureEnabledImpl(Features, "gfni", true);
-    LLVM_FALLTHROUGH;
-  case CK_GoldmontPlus:
-    setFeatureEnabledImpl(Features, "ptwrite", true);
-    setFeatureEnabledImpl(Features, "rdpid", true);
-    setFeatureEnabledImpl(Features, "sgx", true);
-    LLVM_FALLTHROUGH;
-  case CK_Goldmont:
-    setFeatureEnabledImpl(Features, "sha", true);
-    setFeatureEnabledImpl(Features, "rdseed", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    setFeatureEnabledImpl(Features, "xsavec", true);
-    setFeatureEnabledImpl(Features, "xsaves", true);
-    setFeatureEnabledImpl(Features, "clflushopt", true);
-    setFeatureEnabledImpl(Features, "fsgsbase", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    LLVM_FALLTHROUGH;
-  case CK_Silvermont:
-    setFeatureEnabledImpl(Features, "rdrnd", true);
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    setFeatureEnabledImpl(Features, "sse4.2", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    LLVM_FALLTHROUGH;
-  case CK_Bonnell:
-    setFeatureEnabledImpl(Features, "movbe", true);
-    setFeatureEnabledImpl(Features, "ssse3", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "mmx", true);
-    break;
-
-  case CK_KNM:
-    // TODO: Add avx5124fmaps/avx5124vnniw.
-    setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
-    LLVM_FALLTHROUGH;
-  case CK_KNL:
-    setFeatureEnabledImpl(Features, "avx512f", true);
-    setFeatureEnabledImpl(Features, "avx512cd", true);
-    setFeatureEnabledImpl(Features, "avx512er", true);
-    setFeatureEnabledImpl(Features, "avx512pf", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    setFeatureEnabledImpl(Features, "prefetchwt1", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    setFeatureEnabledImpl(Features, "rdseed", true);
-    setFeatureEnabledImpl(Features, "adx", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    setFeatureEnabledImpl(Features, "bmi", true);
-    setFeatureEnabledImpl(Features, "bmi2", true);
-    setFeatureEnabledImpl(Features, "fma", true);
-    setFeatureEnabledImpl(Features, "rdrnd", true);
-    setFeatureEnabledImpl(Features, "f16c", true);
-    setFeatureEnabledImpl(Features, "fsgsbase", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "movbe", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "mmx", true);
-    break;
-
-  case CK_K6_2:
-  case CK_K6_3:
-  case CK_WinChip2:
-  case CK_C3:
-    setFeatureEnabledImpl(Features, "3dnow", true);
-    break;
-
-  case CK_AMDFAM10:
-    setFeatureEnabledImpl(Features, "sse4a", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    LLVM_FALLTHROUGH;
-  case CK_K8SSE3:
-    setFeatureEnabledImpl(Features, "sse3", true);
-    LLVM_FALLTHROUGH;
-  case CK_K8:
-    setFeatureEnabledImpl(Features, "sse2", true);
-    LLVM_FALLTHROUGH;
-  case CK_AthlonXP:
-    setFeatureEnabledImpl(Features, "sse", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    LLVM_FALLTHROUGH;
-  case CK_Athlon:
-  case CK_Geode:
-    setFeatureEnabledImpl(Features, "3dnowa", true);
-    break;
-
-  case CK_BTVER2:
-    setFeatureEnabledImpl(Features, "avx", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    setFeatureEnabledImpl(Features, "bmi", true);
-    setFeatureEnabledImpl(Features, "f16c", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "movbe", true);
-    LLVM_FALLTHROUGH;
-  case CK_BTVER1:
-    setFeatureEnabledImpl(Features, "ssse3", true);
-    setFeatureEnabledImpl(Features, "sse4a", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "mmx", true);
-    break;
-
-  case CK_ZNVER2:
-    setFeatureEnabledImpl(Features, "clwb", true);
-    setFeatureEnabledImpl(Features, "rdpid", true);
-    setFeatureEnabledImpl(Features, "wbnoinvd", true);
-    LLVM_FALLTHROUGH;
-  case CK_ZNVER1:
-    setFeatureEnabledImpl(Features, "adx", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    setFeatureEnabledImpl(Features, "avx2", true);
-    setFeatureEnabledImpl(Features, "bmi", true);
-    setFeatureEnabledImpl(Features, "bmi2", true);
-    setFeatureEnabledImpl(Features, "clflushopt", true);
-    setFeatureEnabledImpl(Features, "clzero", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    setFeatureEnabledImpl(Features, "f16c", true);
-    setFeatureEnabledImpl(Features, "fma", true);
-    setFeatureEnabledImpl(Features, "fsgsbase", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "mmx", true);
-    setFeatureEnabledImpl(Features, "mwaitx", true);
-    setFeatureEnabledImpl(Features, "movbe", true);
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    setFeatureEnabledImpl(Features, "popcnt", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    setFeatureEnabledImpl(Features, "rdrnd", true);
-    setFeatureEnabledImpl(Features, "rdseed", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "sha", true);
-    setFeatureEnabledImpl(Features, "sse4a", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "xsavec", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    setFeatureEnabledImpl(Features, "xsaves", true);
-    break;
-
-  case CK_BDVER4:
-    setFeatureEnabledImpl(Features, "avx2", true);
-    setFeatureEnabledImpl(Features, "bmi2", true);
-    setFeatureEnabledImpl(Features, "movbe", true);
-    setFeatureEnabledImpl(Features, "rdrnd", true);
-    setFeatureEnabledImpl(Features, "mwaitx", true);
-    LLVM_FALLTHROUGH;
-  case CK_BDVER3:
-    setFeatureEnabledImpl(Features, "fsgsbase", true);
-    setFeatureEnabledImpl(Features, "xsaveopt", true);
-    LLVM_FALLTHROUGH;
-  case CK_BDVER2:
-    setFeatureEnabledImpl(Features, "bmi", true);
-    setFeatureEnabledImpl(Features, "fma", true);
-    setFeatureEnabledImpl(Features, "f16c", true);
-    setFeatureEnabledImpl(Features, "tbm", true);
-    LLVM_FALLTHROUGH;
-  case CK_BDVER1:
-    // xop implies avx, sse4a and fma4.
-    setFeatureEnabledImpl(Features, "xop", true);
-    setFeatureEnabledImpl(Features, "lwp", true);
-    setFeatureEnabledImpl(Features, "lzcnt", true);
-    setFeatureEnabledImpl(Features, "aes", true);
-    setFeatureEnabledImpl(Features, "pclmul", true);
-    setFeatureEnabledImpl(Features, "prfchw", true);
-    setFeatureEnabledImpl(Features, "cx16", true);
-    setFeatureEnabledImpl(Features, "fxsr", true);
-    setFeatureEnabledImpl(Features, "xsave", true);
-    setFeatureEnabledImpl(Features, "sahf", true);
-    setFeatureEnabledImpl(Features, "mmx", true);
-    break;
-  }
   if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
     return false;
 
@@ -1531,7 +1201,7 @@ bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
 
 static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
   return llvm::StringSwitch<llvm::X86::ProcessorFeatures>(Name)
-#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, llvm::X86::ENUM)
+#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, llvm::X86::FEATURE_##ENUM)
 #include "llvm/Support/X86TargetParser.def"
       ;
   // Note, this function should only be used after ensuring the value is
index 0a3adf6..265fee3 100644 (file)
@@ -11688,7 +11688,7 @@ CodeGenFunction::GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
   for (const StringRef &FeatureStr : FeatureStrs) {
     unsigned Feature =
         StringSwitch<unsigned>(FeatureStr)
-#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, llvm::X86::ENUM)
+#define X86_FEATURE_COMPAT(ENUM, STR) .Case(STR, llvm::X86::FEATURE_##ENUM)
 #include "llvm/Support/X86TargetParser.def"
         ;
     FeaturesMask |= (1ULL << Feature);
index 58c6e43..c3a144e 100644 (file)
@@ -125,56 +125,97 @@ X86_CPU_SUBTYPE       ("geode",          AMDPENTIUM_GEODE)
 
 // This macro is used for cpu types present in compiler-rt/libgcc.
 #ifndef X86_FEATURE_COMPAT
-#define X86_FEATURE_COMPAT(ENUM, STR) X86_FEATURE(ENUM)
+#define X86_FEATURE_COMPAT(ENUM, STR) X86_FEATURE(ENUM, STR)
 #endif
 
 #ifndef X86_FEATURE
-#define X86_FEATURE(ENUM)
+#define X86_FEATURE(ENUM, STR)
 #endif
 
-X86_FEATURE_COMPAT(FEATURE_CMOV,            "cmov")
-X86_FEATURE_COMPAT(FEATURE_MMX,             "mmx")
-X86_FEATURE_COMPAT(FEATURE_POPCNT,          "popcnt")
-X86_FEATURE_COMPAT(FEATURE_SSE,             "sse")
-X86_FEATURE_COMPAT(FEATURE_SSE2,            "sse2")
-X86_FEATURE_COMPAT(FEATURE_SSE3,            "sse3")
-X86_FEATURE_COMPAT(FEATURE_SSSE3,           "ssse3")
-X86_FEATURE_COMPAT(FEATURE_SSE4_1,          "sse4.1")
-X86_FEATURE_COMPAT(FEATURE_SSE4_2,          "sse4.2")
-X86_FEATURE_COMPAT(FEATURE_AVX,             "avx")
-X86_FEATURE_COMPAT(FEATURE_AVX2,            "avx2")
-X86_FEATURE_COMPAT(FEATURE_SSE4_A,          "sse4a")
-X86_FEATURE_COMPAT(FEATURE_FMA4,            "fma4")
-X86_FEATURE_COMPAT(FEATURE_XOP,             "xop")
-X86_FEATURE_COMPAT(FEATURE_FMA,             "fma")
-X86_FEATURE_COMPAT(FEATURE_AVX512F,         "avx512f")
-X86_FEATURE_COMPAT(FEATURE_BMI,             "bmi")
-X86_FEATURE_COMPAT(FEATURE_BMI2,            "bmi2")
-X86_FEATURE_COMPAT(FEATURE_AES,             "aes")
-X86_FEATURE_COMPAT(FEATURE_PCLMUL,          "pclmul")
-X86_FEATURE_COMPAT(FEATURE_AVX512VL,        "avx512vl")
-X86_FEATURE_COMPAT(FEATURE_AVX512BW,        "avx512bw")
-X86_FEATURE_COMPAT(FEATURE_AVX512DQ,        "avx512dq")
-X86_FEATURE_COMPAT(FEATURE_AVX512CD,        "avx512cd")
-X86_FEATURE_COMPAT(FEATURE_AVX512ER,        "avx512er")
-X86_FEATURE_COMPAT(FEATURE_AVX512PF,        "avx512pf")
-X86_FEATURE_COMPAT(FEATURE_AVX512VBMI,      "avx512vbmi")
-X86_FEATURE_COMPAT(FEATURE_AVX512IFMA,      "avx512ifma")
-X86_FEATURE_COMPAT(FEATURE_AVX5124VNNIW,    "avx5124vnniw")
-X86_FEATURE_COMPAT(FEATURE_AVX5124FMAPS,    "avx5124fmaps")
-X86_FEATURE_COMPAT(FEATURE_AVX512VPOPCNTDQ, "avx512vpopcntdq")
-X86_FEATURE_COMPAT(FEATURE_AVX512VBMI2,     "avx512vbmi2")
-X86_FEATURE_COMPAT(FEATURE_GFNI,            "gfni")
-X86_FEATURE_COMPAT(FEATURE_VPCLMULQDQ,      "vpclmulqdq")
-X86_FEATURE_COMPAT(FEATURE_AVX512VNNI,      "avx512vnni")
-X86_FEATURE_COMPAT(FEATURE_AVX512BITALG,    "avx512bitalg")
-X86_FEATURE_COMPAT(FEATURE_AVX512BF16,      "avx512bf16")
-X86_FEATURE_COMPAT(FEATURE_AVX512VP2INTERSECT, "avx512vp2intersect")
+X86_FEATURE_COMPAT(CMOV,            "cmov")
+X86_FEATURE_COMPAT(MMX,             "mmx")
+X86_FEATURE_COMPAT(POPCNT,          "popcnt")
+X86_FEATURE_COMPAT(SSE,             "sse")
+X86_FEATURE_COMPAT(SSE2,            "sse2")
+X86_FEATURE_COMPAT(SSE3,            "sse3")
+X86_FEATURE_COMPAT(SSSE3,           "ssse3")
+X86_FEATURE_COMPAT(SSE4_1,          "sse4.1")
+X86_FEATURE_COMPAT(SSE4_2,          "sse4.2")
+X86_FEATURE_COMPAT(AVX,             "avx")
+X86_FEATURE_COMPAT(AVX2,            "avx2")
+X86_FEATURE_COMPAT(SSE4_A,          "sse4a")
+X86_FEATURE_COMPAT(FMA4,            "fma4")
+X86_FEATURE_COMPAT(XOP,             "xop")
+X86_FEATURE_COMPAT(FMA,             "fma")
+X86_FEATURE_COMPAT(AVX512F,         "avx512f")
+X86_FEATURE_COMPAT(BMI,             "bmi")
+X86_FEATURE_COMPAT(BMI2,            "bmi2")
+X86_FEATURE_COMPAT(AES,             "aes")
+X86_FEATURE_COMPAT(PCLMUL,          "pclmul")
+X86_FEATURE_COMPAT(AVX512VL,        "avx512vl")
+X86_FEATURE_COMPAT(AVX512BW,        "avx512bw")
+X86_FEATURE_COMPAT(AVX512DQ,        "avx512dq")
+X86_FEATURE_COMPAT(AVX512CD,        "avx512cd")
+X86_FEATURE_COMPAT(AVX512ER,        "avx512er")
+X86_FEATURE_COMPAT(AVX512PF,        "avx512pf")
+X86_FEATURE_COMPAT(AVX512VBMI,      "avx512vbmi")
+X86_FEATURE_COMPAT(AVX512IFMA,      "avx512ifma")
+X86_FEATURE_COMPAT(AVX5124VNNIW,    "avx5124vnniw")
+X86_FEATURE_COMPAT(AVX5124FMAPS,    "avx5124fmaps")
+X86_FEATURE_COMPAT(AVX512VPOPCNTDQ, "avx512vpopcntdq")
+X86_FEATURE_COMPAT(AVX512VBMI2,     "avx512vbmi2")
+X86_FEATURE_COMPAT(GFNI,            "gfni")
+X86_FEATURE_COMPAT(VPCLMULQDQ,      "vpclmulqdq")
+X86_FEATURE_COMPAT(AVX512VNNI,      "avx512vnni")
+X86_FEATURE_COMPAT(AVX512BITALG,    "avx512bitalg")
+X86_FEATURE_COMPAT(AVX512BF16,      "avx512bf16")
+X86_FEATURE_COMPAT(AVX512VP2INTERSECT, "avx512vp2intersect")
 // Features below here are not in libgcc/compiler-rt.
-X86_FEATURE       (FEATURE_MOVBE)
-X86_FEATURE       (FEATURE_ADX)
-X86_FEATURE       (FEATURE_EM64T)
-X86_FEATURE       (FEATURE_CLFLUSHOPT)
-X86_FEATURE       (FEATURE_SHA)
+X86_FEATURE       (3DNOW,           "3dnow")
+X86_FEATURE       (3DNOWA,          "3dnowa")
+X86_FEATURE       (ADX,             "adx")
+X86_FEATURE       (CLDEMOTE,        "cldemote")
+X86_FEATURE       (CLFLUSHOPT,      "clflushopt")
+X86_FEATURE       (CLWB,            "clwb")
+X86_FEATURE       (CLZERO,          "clzero")
+X86_FEATURE       (CMPXCHG16B,      "cx16")
+X86_FEATURE       (CMPXCHG8B,       "cx8")
+X86_FEATURE       (EM64T,           nullptr)
+X86_FEATURE       (ENQCMD,          "enqcmd")
+X86_FEATURE       (F16C,            "f16c")
+X86_FEATURE       (FSGSBASE,        "fsgsbase")
+X86_FEATURE       (FXSR,            "fxsr")
+X86_FEATURE       (INVPCID,         "invpcid")
+X86_FEATURE       (LWP,             "lwp")
+X86_FEATURE       (LZCNT,           "lzcnt")
+X86_FEATURE       (MOVBE,           "movbe")
+X86_FEATURE       (MOVDIR64B,       "movdir64b")
+X86_FEATURE       (MOVDIRI,         "movdiri")
+X86_FEATURE       (MWAITX,          "mwaitx")
+X86_FEATURE       (PCONFIG,         "pconfig")
+X86_FEATURE       (PKU,             "pku")
+X86_FEATURE       (PREFETCHWT1,     "prefetchwt1")
+X86_FEATURE       (PRFCHW,          "prfchw")
+X86_FEATURE       (PTWRITE,         "ptwrite")
+X86_FEATURE       (RDPID,           "rdpid")
+X86_FEATURE       (RDRND,           "rdrnd")
+X86_FEATURE       (RDSEED,          "rdseed")
+X86_FEATURE       (RTM,             "rtm")
+X86_FEATURE       (SAHF,            "sahf")
+X86_FEATURE       (SERIALIZE,       "serialize")
+X86_FEATURE       (SGX,             "sgx")
+X86_FEATURE       (SHA,             "sha")
+X86_FEATURE       (SHSTK,           "shstk")
+X86_FEATURE       (SSE4A,           "sse4a")
+X86_FEATURE       (TBM,             "tbm")
+X86_FEATURE       (TSXLDTRK,        "tsxldtrk")
+X86_FEATURE       (VAES,            "vaes")
+X86_FEATURE       (WAITPKG,         "waitpkg")
+X86_FEATURE       (WBNOINVD,        "wbnoinvd")
+X86_FEATURE       (X87,             "x87")
+X86_FEATURE       (XSAVE,           "xsave")
+X86_FEATURE       (XSAVEC,          "xsavec")
+X86_FEATURE       (XSAVEOPT,        "xsaveopt")
+X86_FEATURE       (XSAVES,          "xsaves")
 #undef X86_FEATURE_COMPAT
 #undef X86_FEATURE
index 99ae400..5897e79 100644 (file)
@@ -53,8 +53,7 @@ enum ProcessorSubtypes : unsigned {
 // This should be kept in sync with libcc/compiler-rt as it should be used
 // by clang as a proxy for what's in libgcc/compiler-rt.
 enum ProcessorFeatures {
-#define X86_FEATURE(ENUM) \
-  ENUM,
+#define X86_FEATURE(ENUM, STRING) FEATURE_##ENUM,
 #include "llvm/Support/X86TargetParser.def"
   CPU_FEATURE_MAX
 };
@@ -132,8 +131,12 @@ CPUKind parseArchX86(StringRef CPU, bool Only64Bit = false);
 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
                           bool ArchIs32Bit);
 
+/// Get the key feature prioritizing target multiversioning.
 ProcessorFeatures getKeyFeature(CPUKind Kind);
 
+/// Fill in the features that \p CPU supports into \p Features.
+void getFeaturesForCPU(StringRef CPU, SmallVectorImpl<StringRef> &Features);
+
 } // namespace X86
 } // namespace llvm
 
index cc3c177..2d70ec4 100644 (file)
@@ -19,134 +19,339 @@ using namespace llvm::X86;
 
 namespace {
 
+/// Container class for CPU features.
+/// This is a constexpr reimplementation of a subset of std::bitset. It would be
+/// nice to use std::bitset directly, but it doesn't support constant
+/// initialization.
+class FeatureBitset {
+  static constexpr unsigned NUM_FEATURE_WORDS =
+      (X86::CPU_FEATURE_MAX + 31) / 32;
+
+  // This cannot be a std::array, operator[] is not constexpr until C++17.
+  uint32_t Bits[NUM_FEATURE_WORDS] = {};
+
+public:
+  constexpr FeatureBitset() = default;
+  constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
+    for (auto I : Init)
+      set(I);
+  }
+
+  constexpr FeatureBitset &set(unsigned I) {
+    uint32_t NewBits = Bits[I / 32] | (uint32_t(1) << (I % 32));
+    Bits[I / 32] = NewBits;
+    return *this;
+  }
+
+  constexpr bool operator[](unsigned I) const {
+    uint32_t Mask = uint32_t(1) << (I % 32);
+    return (Bits[I / 32] & Mask) != 0;
+  }
+
+  constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
+    FeatureBitset Result;
+    for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
+      Result.Bits[I] = Bits[I] & RHS.Bits[I];
+    return Result;
+  }
+
+  constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
+    FeatureBitset Result;
+    for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
+      Result.Bits[I] = Bits[I] | RHS.Bits[I];
+    return Result;
+  }
+
+  constexpr FeatureBitset operator~() const {
+    FeatureBitset Result;
+    for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
+      Result.Bits[I] = ~Bits[I];
+    return Result;
+  }
+};
+
 struct ProcInfo {
   StringLiteral Name;
   X86::CPUKind Kind;
   unsigned KeyFeature;
-  bool Is64Bit;
+  FeatureBitset Features;
 };
 
 } // end anonymous namespace
 
-#define PROC_64_BIT true
-#define PROC_32_BIT false
+#define X86_FEATURE(ENUM, STRING)                                              \
+  static constexpr FeatureBitset Feature##ENUM = {X86::FEATURE_##ENUM};
+#include "llvm/Support/X86TargetParser.def"
+
+// Pentium with MMX.
+static constexpr FeatureBitset FeaturesPentiumMMX =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureMMX;
+
+// Pentium 2 and 3.
+static constexpr FeatureBitset FeaturesPentium2 =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | FeatureFXSR;
+static constexpr FeatureBitset FeaturesPentium3 = FeaturesPentium2 | FeatureSSE;
+
+// Pentium 4 CPUs
+static constexpr FeatureBitset FeaturesPentium4 =
+    FeaturesPentium3 | FeatureSSE2;
+static constexpr FeatureBitset FeaturesPrescott =
+    FeaturesPentium4 | FeatureSSE3;
+static constexpr FeatureBitset FeaturesNocona =
+    FeaturesPrescott | FeatureEM64T | FeatureCMPXCHG16B;
+
+// Basic 64-bit capable CPU.
+static constexpr FeatureBitset FeaturesX86_64 = FeaturesPentium4 | FeatureEM64T;
+
+// Intel Core CPUs
+static constexpr FeatureBitset FeaturesCore2 =
+    FeaturesNocona | FeatureSAHF | FeatureSSSE3;
+static constexpr FeatureBitset FeaturesPenryn = FeaturesCore2 | FeatureSSE4_1;
+static constexpr FeatureBitset FeaturesNehalem =
+    FeaturesPenryn | FeaturePOPCNT | FeatureSSE4_2;
+static constexpr FeatureBitset FeaturesWestmere =
+    FeaturesNehalem | FeaturePCLMUL;
+static constexpr FeatureBitset FeaturesSandyBridge =
+    FeaturesWestmere | FeatureAVX | FeatureXSAVE | FeatureXSAVEOPT;
+static constexpr FeatureBitset FeaturesIvyBridge =
+    FeaturesSandyBridge | FeatureF16C | FeatureFSGSBASE | FeatureRDRND;
+static constexpr FeatureBitset FeaturesHaswell =
+    FeaturesIvyBridge | FeatureAVX2 | FeatureBMI | FeatureBMI2 | FeatureFMA |
+    FeatureINVPCID | FeatureLZCNT | FeatureMOVBE;
+static constexpr FeatureBitset FeaturesBroadwell =
+    FeaturesHaswell | FeatureADX | FeaturePRFCHW | FeatureRDSEED;
+
+// Intel Knights Landing and Knights Mill
+// Knights Landing has feature parity with Broadwell.
+static constexpr FeatureBitset FeaturesKNL =
+    FeaturesBroadwell | FeatureAES | FeatureAVX512F | FeatureAVX512CD |
+    FeatureAVX512ER | FeatureAVX512PF | FeaturePREFETCHWT1;
+static constexpr FeatureBitset FeaturesKNM =
+    FeaturesKNL | FeatureAVX512VPOPCNTDQ;
+
+// Intel Skylake processors.
+static constexpr FeatureBitset FeaturesSkylakeClient =
+    FeaturesBroadwell | FeatureAES | FeatureCLFLUSHOPT | FeatureXSAVEC |
+    FeatureXSAVES | FeatureSGX;
+// SkylakeServer inherits all SkylakeClient features except SGX.
+// FIXME: That doesn't match gcc.
+static constexpr FeatureBitset FeaturesSkylakeServer =
+    (FeaturesSkylakeClient & ~FeatureSGX) | FeatureAVX512F | FeatureAVX512CD |
+    FeatureAVX512DQ | FeatureAVX512BW | FeatureAVX512VL | FeatureCLWB |
+    FeaturePKU;
+static constexpr FeatureBitset FeaturesCascadeLake =
+    FeaturesSkylakeServer | FeatureAVX512VNNI;
+static constexpr FeatureBitset FeaturesCooperLake =
+    FeaturesCascadeLake | FeatureAVX512BF16;
+
+// Intel 10nm processors.
+static constexpr FeatureBitset FeaturesCannonlake =
+    FeaturesSkylakeClient | FeatureAVX512F | FeatureAVX512CD | FeatureAVX512DQ |
+    FeatureAVX512BW | FeatureAVX512VL | FeatureAVX512IFMA | FeatureAVX512VBMI |
+    FeaturePKU | FeatureSHA;
+static constexpr FeatureBitset FeaturesICLClient =
+    FeaturesCannonlake | FeatureAVX512BITALG | FeatureAVX512VBMI2 |
+    FeatureAVX512VNNI | FeatureAVX512VPOPCNTDQ | FeatureCLWB | FeatureGFNI |
+    FeatureRDPID | FeatureVAES | FeatureVPCLMULQDQ;
+static constexpr FeatureBitset FeaturesICLServer =
+    FeaturesICLClient | FeaturePCONFIG | FeatureWBNOINVD;
+static constexpr FeatureBitset FeaturesTigerlake =
+    FeaturesICLClient | FeatureAVX512VP2INTERSECT | FeatureMOVDIR64B |
+    FeatureMOVDIRI | FeatureSHSTK;
+
+// Intel Atom processors.
+// Bonnell has feature parity with Core2 and adds MOVBE.
+static constexpr FeatureBitset FeaturesBonnell = FeaturesCore2 | FeatureMOVBE;
+// Silvermont has parity with Westmere and Bonnell plus PRFCHW and RDRND.
+static constexpr FeatureBitset FeaturesSilvermont =
+    FeaturesBonnell | FeaturesWestmere | FeaturePRFCHW | FeatureRDRND;
+static constexpr FeatureBitset FeaturesGoldmont =
+    FeaturesSilvermont | FeatureAES | FeatureCLFLUSHOPT | FeatureFSGSBASE |
+    FeatureRDSEED | FeatureSHA | FeatureXSAVE | FeatureXSAVEC |
+    FeatureXSAVEOPT | FeatureXSAVES;
+static constexpr FeatureBitset FeaturesGoldmontPlus =
+    FeaturesGoldmont | FeaturePTWRITE | FeatureRDPID | FeatureSGX;
+static constexpr FeatureBitset FeaturesTremont =
+    FeaturesGoldmontPlus | FeatureCLWB | FeatureGFNI;
+
+// Geode Processor.
+static constexpr FeatureBitset FeaturesGeode =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | Feature3DNOW | Feature3DNOWA;
+
+// K6 processor.
+static constexpr FeatureBitset FeaturesK6 =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureMMX;
+
+// K7 and K8 architecture processors.
+static constexpr FeatureBitset FeaturesAthlon =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | Feature3DNOW | Feature3DNOWA;
+static constexpr FeatureBitset FeaturesAthlonXP =
+    FeaturesAthlon | FeatureFXSR | FeatureSSE;
+static constexpr FeatureBitset FeaturesK8 =
+    FeaturesAthlonXP | FeatureSSE2 | FeatureEM64T;
+static constexpr FeatureBitset FeaturesK8SSE3 = FeaturesK8 | FeatureSSE3;
+static constexpr FeatureBitset FeaturesAMDFAM10 =
+    FeaturesK8SSE3 | FeatureCMPXCHG16B | FeatureLZCNT | FeaturePOPCNT |
+    FeaturePRFCHW | FeatureSAHF | FeatureSSE4A;
+
+// Bobcat architecture processors.
+static constexpr FeatureBitset FeaturesBTVER1 =
+    FeatureX87 | FeatureCMPXCHG8B | FeatureCMPXCHG16B | FeatureEM64T |
+    FeatureFXSR | FeatureLZCNT | FeatureMMX | FeaturePOPCNT | FeaturePRFCHW |
+    FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 | FeatureSSE4A |
+    FeatureSAHF;
+static constexpr FeatureBitset FeaturesBTVER2 =
+    FeaturesBTVER1 | FeatureAES | FeatureAVX | FeatureBMI | FeatureF16C |
+    FeatureMOVBE | FeaturePCLMUL | FeatureXSAVE | FeatureXSAVEOPT;
+
+// AMD Bulldozer architecture processors.
+static constexpr FeatureBitset FeaturesBDVER1 =
+    FeatureX87 | FeatureAES | FeatureAVX | FeatureCMPXCHG8B |
+    FeatureCMPXCHG16B | FeatureEM64T | FeatureFMA4 | FeatureFXSR |
+    FeatureLZCNT | FeatureLWP | FeatureLZCNT | FeatureMMX | FeaturePCLMUL |
+    FeaturePOPCNT | FeaturePRFCHW | FeatureSAHF | FeatureSSE | FeatureSSE2 |
+    FeatureSSE3 | FeatureSSSE3 | FeatureSSE4_1 | FeatureSSE4_2 | FeatureSSE4A |
+    FeatureXOP | FeatureXSAVE;
+static constexpr FeatureBitset FeaturesBDVER2 =
+    FeaturesBDVER1 | FeatureBMI | FeatureFMA | FeatureF16C | FeatureTBM;
+static constexpr FeatureBitset FeaturesBDVER3 =
+    FeaturesBDVER2 | FeatureFSGSBASE | FeatureXSAVEOPT;
+static constexpr FeatureBitset FeaturesBDVER4 =
+    FeaturesBDVER3 | FeatureAVX2 | FeatureBMI2 | FeatureMOVBE | FeatureMWAITX |
+    FeatureRDRND;
+
+// AMD Zen architecture processors.
+static constexpr FeatureBitset FeaturesZNVER1 =
+    FeatureX87 | FeatureADX | FeatureAES | FeatureAVX | FeatureAVX2 |
+    FeatureBMI | FeatureBMI2 | FeatureCLFLUSHOPT | FeatureCLZERO |
+    FeatureCMPXCHG8B | FeatureCMPXCHG16B | FeatureEM64T | FeatureF16C |
+    FeatureFMA | FeatureFSGSBASE | FeatureFXSR | FeatureLZCNT | FeatureLWP |
+    FeatureLZCNT | FeatureMOVBE | FeatureMMX | FeatureMWAITX | FeaturePCLMUL |
+    FeaturePOPCNT | FeaturePRFCHW | FeatureRDRND | FeatureRDSEED | FeatureSAHF |
+    FeatureSHA | FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 |
+    FeatureSSE4_1 | FeatureSSE4_2 | FeatureSSE4A | FeatureXSAVE |
+    FeatureXSAVEC | FeatureXSAVEOPT | FeatureXSAVES;
+static constexpr FeatureBitset FeaturesZNVER2 =
+    FeaturesZNVER1 | FeatureCLWB | FeatureRDPID | FeatureWBNOINVD;
 
 static constexpr ProcInfo Processors[] = {
+  // Empty processor. Include X87 and CMPXCHG8 for backwards compatibility.
+  { {""}, CK_None, ~0U, FeatureX87 | FeatureCMPXCHG8B },
   // i386-generation processors.
-  { {"i386"}, CK_i386, ~0U, PROC_32_BIT },
+  { {"i386"}, CK_i386, ~0U, FeatureX87 },
   // i486-generation processors.
-  { {"i486"}, CK_i486, ~0U, PROC_32_BIT },
-  { {"winchip-c6"}, CK_WinChipC6, ~0U, PROC_32_BIT },
-  { {"winchip2"}, CK_WinChip2, ~0U, PROC_32_BIT },
-  { {"c3"}, CK_C3, ~0U, PROC_32_BIT },
+  { {"i486"}, CK_i486, ~0U, FeatureX87 },
+  { {"winchip-c6"}, CK_WinChipC6, ~0U, FeaturesPentiumMMX },
+  { {"winchip2"}, CK_WinChip2, ~0U, FeaturesPentiumMMX | Feature3DNOW },
+  { {"c3"}, CK_C3, ~0U, FeaturesPentiumMMX | Feature3DNOW },
   // i586-generation processors, P5 microarchitecture based.
-  { {"i586"}, CK_i586, ~0U, PROC_32_BIT },
-  { {"pentium"}, CK_Pentium, ~0U, PROC_32_BIT },
-  { {"pentium-mmx"}, CK_PentiumMMX, ~0U, PROC_32_BIT },
-  { {"pentiumpro"}, CK_PentiumPro, ~0U, PROC_32_BIT },
+  { {"i586"}, CK_i586, ~0U, FeatureX87 | FeatureCMPXCHG8B },
+  { {"pentium"}, CK_Pentium, ~0U, FeatureX87 | FeatureCMPXCHG8B },
+  { {"pentium-mmx"}, CK_PentiumMMX, ~0U, FeaturesPentiumMMX },
   // i686-generation processors, P6 / Pentium M microarchitecture based.
-  { {"i686"}, CK_i686, ~0U, PROC_32_BIT },
-  { {"pentium2"}, CK_Pentium2, ~0U, PROC_32_BIT },
-  { {"pentium3"}, CK_Pentium3, ~0U, PROC_32_BIT },
-  { {"pentium3m"}, CK_Pentium3, ~0U, PROC_32_BIT },
-  { {"pentium-m"}, CK_PentiumM, ~0U, PROC_32_BIT },
-  { {"c3-2"}, CK_C3_2, ~0U, PROC_32_BIT },
-  { {"yonah"}, CK_Yonah, ~0U, PROC_32_BIT },
+  { {"pentiumpro"}, CK_PentiumPro, ~0U, FeatureX87 | FeatureCMPXCHG8B },
+  { {"i686"}, CK_i686, ~0U, FeatureX87 | FeatureCMPXCHG8B },
+  { {"pentium2"}, CK_Pentium2, ~0U, FeaturesPentium2 },
+  { {"pentium3"}, CK_Pentium3, ~0U, FeaturesPentium3 },
+  { {"pentium3m"}, CK_Pentium3, ~0U, FeaturesPentium3 },
+  { {"pentium-m"}, CK_PentiumM, ~0U, FeaturesPentium4 },
+  { {"c3-2"}, CK_C3_2, ~0U, FeaturesPentium3 },
+  { {"yonah"}, CK_Yonah, ~0U, FeaturesPrescott },
   // Netburst microarchitecture based processors.
-  { {"pentium4"}, CK_Pentium4, ~0U, PROC_32_BIT },
-  { {"pentium4m"}, CK_Pentium4, ~0U, PROC_32_BIT },
-  { {"prescott"}, CK_Prescott, ~0U, PROC_32_BIT },
-  { {"nocona"}, CK_Nocona, ~0U, PROC_64_BIT },
+  { {"pentium4"}, CK_Pentium4, ~0U, FeaturesPentium4 },
+  { {"pentium4m"}, CK_Pentium4, ~0U, FeaturesPentium4 },
+  { {"prescott"}, CK_Prescott, ~0U, FeaturesPrescott },
+  { {"nocona"}, CK_Nocona, ~0U, FeaturesNocona },
   // Core microarchitecture based processors.
-  { {"core2"}, CK_Core2, ~0U, PROC_64_BIT },
-  { {"penryn"}, CK_Penryn, ~0U, PROC_64_BIT },
+  { {"core2"}, CK_Core2, ~0U, FeaturesCore2 },
+  { {"penryn"}, CK_Penryn, ~0U, FeaturesPenryn },
   // Atom processors
-  { {"bonnell"}, CK_Bonnell, FEATURE_SSSE3, PROC_64_BIT },
-  { {"atom"}, CK_Bonnell, FEATURE_SSSE3, PROC_64_BIT },
-  { {"silvermont"}, CK_Silvermont, FEATURE_SSE4_2, PROC_64_BIT },
-  { {"slm"}, CK_Silvermont, FEATURE_SSE4_2, PROC_64_BIT },
-  { {"goldmont"}, CK_Goldmont, FEATURE_SSE4_2, PROC_64_BIT },
-  { {"goldmont-plus"}, CK_GoldmontPlus, FEATURE_SSE4_2, PROC_64_BIT },
-  { {"tremont"}, CK_Tremont, FEATURE_SSE4_2, PROC_64_BIT },
+  { {"bonnell"}, CK_Bonnell, FEATURE_SSSE3, FeaturesBonnell },
+  { {"atom"}, CK_Bonnell, FEATURE_SSSE3, FeaturesBonnell },
+  { {"silvermont"}, CK_Silvermont, FEATURE_SSE4_2, FeaturesSilvermont },
+  { {"slm"}, CK_Silvermont, FEATURE_SSE4_2, FeaturesSilvermont },
+  { {"goldmont"}, CK_Goldmont, FEATURE_SSE4_2, FeaturesGoldmont },
+  { {"goldmont-plus"}, CK_GoldmontPlus, FEATURE_SSE4_2, FeaturesGoldmontPlus },
+  { {"tremont"}, CK_Tremont, FEATURE_SSE4_2, FeaturesTremont },
   // Nehalem microarchitecture based processors.
-  { {"nehalem"}, CK_Nehalem, FEATURE_SSE4_2, PROC_64_BIT },
-  { {"corei7"}, CK_Nehalem, FEATURE_SSE4_2, PROC_64_BIT },
+  { {"nehalem"}, CK_Nehalem, FEATURE_SSE4_2, FeaturesNehalem },
+  { {"corei7"}, CK_Nehalem, FEATURE_SSE4_2, FeaturesNehalem },
   // Westmere microarchitecture based processors.
-  { {"westmere"}, CK_Westmere, FEATURE_PCLMUL, PROC_64_BIT },
+  { {"westmere"}, CK_Westmere, FEATURE_PCLMUL, FeaturesWestmere },
   // Sandy Bridge microarchitecture based processors.
-  { {"sandybridge"}, CK_SandyBridge, FEATURE_AVX, PROC_64_BIT },
-  { {"corei7-avx"}, CK_SandyBridge, FEATURE_AVX, PROC_64_BIT },
+  { {"sandybridge"}, CK_SandyBridge, FEATURE_AVX, FeaturesSandyBridge },
+  { {"corei7-avx"}, CK_SandyBridge, FEATURE_AVX, FeaturesSandyBridge },
   // Ivy Bridge microarchitecture based processors.
-  { {"ivybridge"}, CK_IvyBridge, FEATURE_AVX, PROC_64_BIT },
-  { {"core-avx-i"}, CK_IvyBridge, FEATURE_AVX, PROC_64_BIT },
+  { {"ivybridge"}, CK_IvyBridge, FEATURE_AVX, FeaturesIvyBridge },
+  { {"core-avx-i"}, CK_IvyBridge, FEATURE_AVX, FeaturesIvyBridge },
   // Haswell microarchitecture based processors.
-  { {"haswell"}, CK_Haswell, FEATURE_AVX2, PROC_64_BIT },
-  { {"core-avx2"}, CK_Haswell, FEATURE_AVX2, PROC_64_BIT },
+  { {"haswell"}, CK_Haswell, FEATURE_AVX2, FeaturesHaswell },
+  { {"core-avx2"}, CK_Haswell, FEATURE_AVX2, FeaturesHaswell },
   // Broadwell microarchitecture based processors.
-  { {"broadwell"}, CK_Broadwell, FEATURE_AVX2, PROC_64_BIT },
+  { {"broadwell"}, CK_Broadwell, FEATURE_AVX2, FeaturesBroadwell },
   // Skylake client microarchitecture based processors.
-  { {"skylake"}, CK_SkylakeClient, FEATURE_AVX2, PROC_64_BIT },
+  { {"skylake"}, CK_SkylakeClient, FEATURE_AVX2, FeaturesSkylakeClient },
   // Skylake server microarchitecture based processors.
-  { {"skylake-avx512"}, CK_SkylakeServer, FEATURE_AVX512F, PROC_64_BIT },
-  { {"skx"}, CK_SkylakeServer, FEATURE_AVX512F, PROC_64_BIT },
+  { {"skylake-avx512"}, CK_SkylakeServer, FEATURE_AVX512F, FeaturesSkylakeServer },
+  { {"skx"}, CK_SkylakeServer, FEATURE_AVX512F, FeaturesSkylakeServer },
   // Cascadelake Server microarchitecture based processors.
-  { {"cascadelake"}, CK_Cascadelake, FEATURE_AVX512VNNI, PROC_64_BIT },
+  { {"cascadelake"}, CK_Cascadelake, FEATURE_AVX512VNNI, FeaturesCascadeLake },
   // Cooperlake Server microarchitecture based processors.
-  { {"cooperlake"}, CK_Cooperlake, FEATURE_AVX512BF16, PROC_64_BIT },
+  { {"cooperlake"}, CK_Cooperlake, FEATURE_AVX512BF16, FeaturesCooperLake },
   // Cannonlake client microarchitecture based processors.
-  { {"cannonlake"}, CK_Cannonlake, FEATURE_AVX512VBMI, PROC_64_BIT },
+  { {"cannonlake"}, CK_Cannonlake, FEATURE_AVX512VBMI, FeaturesCannonlake },
   // Icelake client microarchitecture based processors.
-  { {"icelake-client"}, CK_IcelakeClient, FEATURE_AVX512VBMI2, PROC_64_BIT },
+  { {"icelake-client"}, CK_IcelakeClient, FEATURE_AVX512VBMI2, FeaturesICLClient },
   // Icelake server microarchitecture based processors.
-  { {"icelake-server"}, CK_IcelakeServer, FEATURE_AVX512VBMI2, PROC_64_BIT },
+  { {"icelake-server"}, CK_IcelakeServer, FEATURE_AVX512VBMI2, FeaturesICLServer },
   // Tigerlake microarchitecture based processors.
-  { {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, PROC_64_BIT },
+  { {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, FeaturesTigerlake },
   // Knights Landing processor.
-  { {"knl"}, CK_KNL, FEATURE_AVX512F, PROC_64_BIT },
+  { {"knl"}, CK_KNL, FEATURE_AVX512F, FeaturesKNL },
   // Knights Mill processor.
-  { {"knm"}, CK_KNM, FEATURE_AVX5124FMAPS, PROC_64_BIT },
+  { {"knm"}, CK_KNM, FEATURE_AVX5124FMAPS, FeaturesKNM },
   // Lakemont microarchitecture based processors.
-  { {"lakemont"}, CK_Lakemont, ~0U, PROC_32_BIT },
+  { {"lakemont"}, CK_Lakemont, ~0U, FeatureCMPXCHG8B },
   // K6 architecture processors.
-  { {"k6"}, CK_K6, ~0U, PROC_32_BIT },
-  { {"k6-2"}, CK_K6_2, ~0U, PROC_32_BIT },
-  { {"k6-3"}, CK_K6_3, ~0U, PROC_32_BIT },
+  { {"k6"}, CK_K6, ~0U, FeaturesK6 },
+  { {"k6-2"}, CK_K6_2, ~0U, FeaturesK6 | Feature3DNOW },
+  { {"k6-3"}, CK_K6_3, ~0U, FeaturesK6 | Feature3DNOW },
   // K7 architecture processors.
-  { {"athlon"}, CK_Athlon, ~0U, PROC_32_BIT },
-  { {"athlon-tbird"}, CK_Athlon, ~0U, PROC_32_BIT },
-  { {"athlon-xp"}, CK_AthlonXP, ~0U, PROC_32_BIT },
-  { {"athlon-mp"}, CK_AthlonXP, ~0U, PROC_32_BIT },
-  { {"athlon-4"}, CK_AthlonXP, ~0U, PROC_32_BIT },
+  { {"athlon"}, CK_Athlon, ~0U, FeaturesAthlon },
+  { {"athlon-tbird"}, CK_Athlon, ~0U, FeaturesAthlon },
+  { {"athlon-xp"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
+  { {"athlon-mp"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
+  { {"athlon-4"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
   // K8 architecture processors.
-  { {"k8"}, CK_K8, ~0U, PROC_64_BIT },
-  { {"athlon64"}, CK_K8, ~0U, PROC_64_BIT },
-  { {"athlon-fx"}, CK_K8, ~0U, PROC_64_BIT },
-  { {"opteron"}, CK_K8, ~0U, PROC_64_BIT },
-  { {"k8-sse3"}, CK_K8SSE3, ~0U, PROC_64_BIT },
-  { {"athlon64-sse3"}, CK_K8SSE3, ~0U, PROC_64_BIT },
-  { {"opteron-sse3"}, CK_K8SSE3, ~0U, PROC_64_BIT },
-  { {"amdfam10"}, CK_AMDFAM10, FEATURE_SSE4_A, PROC_64_BIT },
-  { {"barcelona"}, CK_AMDFAM10, FEATURE_SSE4_A, PROC_64_BIT },
+  { {"k8"}, CK_K8, ~0U, FeaturesK8 },
+  { {"athlon64"}, CK_K8, ~0U, FeaturesK8 },
+  { {"athlon-fx"}, CK_K8, ~0U, FeaturesK8 },
+  { {"opteron"}, CK_K8, ~0U, FeaturesK8 },
+  { {"k8-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
+  { {"athlon64-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
+  { {"opteron-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
+  { {"amdfam10"}, CK_AMDFAM10, FEATURE_SSE4_A, FeaturesAMDFAM10 },
+  { {"barcelona"}, CK_AMDFAM10, FEATURE_SSE4_A, FeaturesAMDFAM10 },
   // Bobcat architecture processors.
-  { {"btver1"}, CK_BTVER1, FEATURE_SSE4_A, PROC_64_BIT },
-  { {"btver2"}, CK_BTVER2, FEATURE_BMI, PROC_64_BIT },
+  { {"btver1"}, CK_BTVER1, FEATURE_SSE4_A, FeaturesBTVER1 },
+  { {"btver2"}, CK_BTVER2, FEATURE_BMI, FeaturesBTVER2 },
   // Bulldozer architecture processors.
-  { {"bdver1"}, CK_BDVER1, FEATURE_XOP, PROC_64_BIT },
-  { {"bdver2"}, CK_BDVER2, FEATURE_FMA, PROC_64_BIT },
-  { {"bdver3"}, CK_BDVER3, FEATURE_FMA, PROC_64_BIT },
-  { {"bdver4"}, CK_BDVER4, FEATURE_AVX2, PROC_64_BIT },
+  { {"bdver1"}, CK_BDVER1, FEATURE_XOP, FeaturesBDVER1 },
+  { {"bdver2"}, CK_BDVER2, FEATURE_FMA, FeaturesBDVER2 },
+  { {"bdver3"}, CK_BDVER3, FEATURE_FMA, FeaturesBDVER3 },
+  { {"bdver4"}, CK_BDVER4, FEATURE_AVX2, FeaturesBDVER4 },
   // Zen architecture processors.
-  { {"znver1"}, CK_ZNVER1, FEATURE_AVX2, PROC_64_BIT },
-  { {"znver2"}, CK_ZNVER2, FEATURE_AVX2, PROC_64_BIT },
+  { {"znver1"}, CK_ZNVER1, FEATURE_AVX2, FeaturesZNVER1 },
+  { {"znver2"}, CK_ZNVER2, FEATURE_AVX2, FeaturesZNVER2 },
   // Generic 64-bit processor.
-  { {"x86-64"}, CK_x86_64, ~0U, PROC_64_BIT },
+  { {"x86-64"}, CK_x86_64, ~0U, FeaturesX86_64 },
   // Geode processors.
-  { {"geode"}, CK_Geode, ~0U, PROC_32_BIT },
+  { {"geode"}, CK_Geode, ~0U, FeaturesGeode },
 };
 
 X86::CPUKind llvm::X86::parseArchX86(StringRef CPU, bool Only64Bit) {
   for (const auto &P : Processors)
-    if (P.Name == CPU && (P.Is64Bit || !Only64Bit))
+    if (P.Name == CPU && (P.Features[FEATURE_EM64T] || !Only64Bit))
       return P.Kind;
 
   return CK_None;
@@ -155,7 +360,7 @@ X86::CPUKind llvm::X86::parseArchX86(StringRef CPU, bool Only64Bit) {
 void llvm::X86::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
                                      bool Only64Bit) {
   for (const auto &P : Processors)
-    if (P.Is64Bit || !Only64Bit)
+    if (!P.Name.empty() && (P.Features[FEATURE_EM64T] || !Only64Bit))
       Values.emplace_back(P.Name);
 }
 
@@ -171,3 +376,20 @@ ProcessorFeatures llvm::X86::getKeyFeature(X86::CPUKind Kind) {
 
   llvm_unreachable("Unable to find CPU kind!");
 }
+
+static const char *FeatureStrings[X86::CPU_FEATURE_MAX] = {
+#define X86_FEATURE(ENUM, STR) STR,
+#include "llvm/Support/X86TargetParser.def"
+};
+
+void llvm::X86::getFeaturesForCPU(StringRef CPU,
+                                  SmallVectorImpl<StringRef> &Features) {
+  auto I = llvm::find_if(Processors,
+                         [&](const ProcInfo &P) { return P.Name == CPU; });
+  assert(I != std::end(Processors) && "Processor not found!");
+
+  // Add the string version of all set bits.
+  for (unsigned i = 0; i != CPU_FEATURE_MAX; ++i)
+    if (FeatureStrings[i] && I->Features[i])
+      Features.push_back(FeatureStrings[i]);
+}