diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
index 274b94d..ee9684a 100644
--- a/include/clang/Basic/CMakeLists.txt
+++ b/include/clang/Basic/CMakeLists.txt
@@ -23,6 +23,14 @@ clang_tablegen(DiagnosticIndexName.inc -gen-clang-diags-index-name
   SOURCE Diagnostic.td
   TARGET ClangDiagnosticIndexName)
 
+clang_tablegen(X86CPUNamesEnum.inc -gen-clang-x86-cpu-names-enum
+  SOURCE X86CPUs.td
+  TARGET ClangX86CPUNamesEnum)
+
+clang_tablegen(X86CPUNamesFuncs.inc -gen-clang-x86-cpu-names-funcs
+  SOURCE X86CPUs.td
+  TARGET ClangX86CPUNamesFuncs)
+
 clang_tablegen(AttrList.inc -gen-clang-attr-list
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE Attr.td
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 6002836..6b80f05 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -44,6 +44,9 @@ class SourceManager;
 
 namespace Builtin { struct Info; }
 
+const char *getX86CPUName(int CPU);
+int getX86CPUFromName(StringRef Name);
+
 /// \brief Exposes information about the current target.
 ///
 class TargetInfo : public RefCountedBase<TargetInfo> {
diff --git a/include/clang/Basic/X86CPUs.td b/include/clang/Basic/X86CPUs.td
new file mode 100644
index 0000000..55cecad
--- /dev/null
+++ b/include/clang/Basic/X86CPUs.td
@@ -0,0 +1,99 @@
+// An X86 CPU
+class X86CPU<string name, bit has64Bits> {
+  string Name = name;
+  bit Has64Bits = has64Bits;
+}
+
+def : X86CPU<"Generic", 0>;
+
+/// i386-generation processors.
+def : X86CPU<"i386", 0>;
+
+/// i486-generation processors.
+def : X86CPU<"i486", 0>;
+def : X86CPU<"winchip-c6", 0>;
+def : X86CPU<"winchip2", 0>;
+def : X86CPU<"c3", 0>;
+
+/// i586-generation processors, P5 microarchitecture based.
+def : X86CPU<"i586", 0>;
+def : X86CPU<"pentium", 0>;
+def : X86CPU<"pentium-mmx", 0>;
+
+/// i686-generation processors, P6 / Pentium M microarchitecture based.
+def : X86CPU<"i686", 0>;
+def : X86CPU<"pentiumpro", 0>;
+def : X86CPU<"pentium2", 0>;
+def : X86CPU<"pentium3", 0>;
+def : X86CPU<"pentium3m", 0>;
+def : X86CPU<"pentium-m", 0>;
+def : X86CPU<"c3-2", 0>;
+
+/// This enumerator is a bit odd, as GCC no longer accepts -march=yonah.
+/// Clang however has some logic to suport this.
+// FIXME: Warn, deprecate, and potentially remove this.
+def : X86CPU<"yonah", 0>;
+
+/// Netburst microarchitecture based processors.
+def : X86CPU<"pentium4", 0>;
+def : X86CPU<"pentium4m", 0>;
+def : X86CPU<"prescott", 0>;
+def : X86CPU<"nocona", 1>;
+
+/// Core microarchitecture based processors.
+def : X86CPU<"core2", 1>;
+
+/// This enumerator, like \see Yonah, is a bit odd. It is another
+/// codename which GCC no longer accepts as an option to -march, but Clang
+/// has some logic for recognizing it.
+// FIXME: Warn, deprecate, and potentially remove this.
+def : X86CPU<"penryn", 1>;
+
+/// \name Atom
+/// Atom processors
+def : X86CPU<"atom", 1>;
+
+/// \name Nehalem
+/// Nehalem microarchitecture based processors.
+def : X86CPU<"corei7", 1>;
+def : X86CPU<"corei7-avx", 1>;
+def : X86CPU<"core-avx-i", 1>;
+def : X86CPU<"core-avx2", 1>;
+
+/// K6 architecture processors.
+def : X86CPU<"k6", 0>;
+def : X86CPU<"k6-2", 0>;
+def : X86CPU<"k6-3", 0>;
+
+/// K7 architecture processors.
+def : X86CPU<"athlon", 0>;
+def : X86CPU<"athlon-tbird", 0>;
+def : X86CPU<"athlon-4", 0>;
+def : X86CPU<"athlon-xp", 0>;
+def : X86CPU<"athlon-mp", 0>;
+
+/// K8 architecture processors.
+def : X86CPU<"athlon64", 1>;
+def : X86CPU<"athlon64-sse3", 1>;
+def : X86CPU<"athlon-fx", 1>;
+def : X86CPU<"k8", 1>;
+def : X86CPU<"k8-sse3", 1>;
+def : X86CPU<"opteron", 1>;
+def : X86CPU<"opteron-sse3", 1>;
+def : X86CPU<"amdfam10", 1>;
+
+/// Bobcat architecture processors.
+def : X86CPU<"btver1", 1>;
+def : X86CPU<"btver2", 1>;
+
+/// Bulldozer architecture processors.
+def : X86CPU<"bdver1", 1>;
+def : X86CPU<"bdver2", 1>;
+
+/// This specification is deprecated and will be removed in the future.
+/// Users should prefer \see K8.
+// FIXME: Warn on this when the CPU is set to it.
+def : X86CPU<"x86-64", 1>;
+
+/// Geode processors.
+def : X86CPU<"geode", 0>;
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 3411169..490f75b 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -65,9 +65,11 @@ add_dependencies(clangBasic
   ClangDiagnosticParse
   ClangDiagnosticSema
   ClangDiagnosticSerialization
+  ClangX86CPUNamesEnum
+  ClangX86CPUNamesFuncs
   )
 
 # clangBasic depends on the version.
 if (Subversion_FOUND AND EXISTS "${CLANG_SOURCE_DIR}/.svn")
   add_dependencies(clangBasic clang_revision_tag)
-endif()
\ No newline at end of file
+endif()
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index f3822ed..8dd73a4 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/MacroBuilder.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/X86CPUNamesEnum.inc"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/STLExtras.h"
@@ -31,6 +32,8 @@
 #include <algorithm>
 using namespace clang;
 
+#include "clang/Basic/X86CPUNamesFuncs.inc"
+
 //===----------------------------------------------------------------------===//
 //  Common code shared among targets.
 //===----------------------------------------------------------------------===//
@@ -1592,146 +1595,7 @@ class X86TargetInfo : public TargetInfo {
   bool HasXOP;
   bool HasF16C;
 
-  /// \brief Enumeration of all of the X86 CPUs supported by Clang.
-  ///
-  /// Each enumeration represents a particular CPU supported by Clang. These
-  /// loosely correspond to the options passed to '-march' or '-mtune' flags.
-  enum CPUKind {
-    CK_Generic,
-
-    /// \name i386
-    /// i386-generation processors.
-    //@{
-    CK_i386,
-    //@}
-
-    /// \name i486
-    /// i486-generation processors.
-    //@{
-    CK_i486,
-    CK_WinChipC6,
-    CK_WinChip2,
-    CK_C3,
-    //@}
-
-    /// \name i586
-    /// i586-generation processors, P5 microarchitecture based.
-    //@{
-    CK_i586,
-    CK_Pentium,
-    CK_PentiumMMX,
-    //@}
-
-    /// \name i686
-    /// i686-generation processors, P6 / Pentium M microarchitecture based.
-    //@{
-    CK_i686,
-    CK_PentiumPro,
-    CK_Pentium2,
-    CK_Pentium3,
-    CK_Pentium3M,
-    CK_PentiumM,
-    CK_C3_2,
-
-    /// This enumerator is a bit odd, as GCC no longer accepts -march=yonah.
-    /// Clang however has some logic to suport this.
-    // FIXME: Warn, deprecate, and potentially remove this.
-    CK_Yonah,
-    //@}
-
-    /// \name Netburst
-    /// Netburst microarchitecture based processors.
-    //@{
-    CK_Pentium4,
-    CK_Pentium4M,
-    CK_Prescott,
-    CK_Nocona,
-    //@}
-
-    /// \name Core
-    /// Core microarchitecture based processors.
-    //@{
-    CK_Core2,
-
-    /// This enumerator, like \see CK_Yonah, is a bit odd. It is another
-    /// codename which GCC no longer accepts as an option to -march, but Clang
-    /// has some logic for recognizing it.
-    // FIXME: Warn, deprecate, and potentially remove this.
-    CK_Penryn,
-    //@}
-
-    /// \name Atom
-    /// Atom processors
-    //@{
-    CK_Atom,
-    //@}
-
-    /// \name Nehalem
-    /// Nehalem microarchitecture based processors.
-    //@{
-    CK_Corei7,
-    CK_Corei7AVX,
-    CK_CoreAVXi,
-    CK_CoreAVX2,
-    //@}
-
-    /// \name K6
-    /// K6 architecture processors.
-    //@{
-    CK_K6,
-    CK_K6_2,
-    CK_K6_3,
-    //@}
-
-    /// \name K7
-    /// K7 architecture processors.
-    //@{
-    CK_Athlon,
-    CK_AthlonThunderbird,
-    CK_Athlon4,
-    CK_AthlonXP,
-    CK_AthlonMP,
-    //@}
-
-    /// \name K8
-    /// K8 architecture processors.
-    //@{
-    CK_Athlon64,
-    CK_Athlon64SSE3,
-    CK_AthlonFX,
-    CK_K8,
-    CK_K8SSE3,
-    CK_Opteron,
-    CK_OpteronSSE3,
-    CK_AMDFAM10,
-    //@}
-
-    /// \name Bobcat
-    /// Bobcat architecture processors.
-    //@{
-    CK_BTVER1,
-    CK_BTVER2,
-    //@}
-
-    /// \name Bulldozer
-    /// Bulldozer architecture processors.
-    //@{
-    CK_BDVER1,
-    CK_BDVER2,
-    //@}
-
-    /// This specification is deprecated and will be removed in the future.
-    /// Users should prefer \see CK_K8.
-    // FIXME: Warn on this when the CPU is set to it.
-    CK_x86_64,
-    //@}
-
-    /// \name Geode
-    /// Geode processors.
-    //@{
-    CK_Geode
-    //@}
-  } CPU;
+  X86CPUKind CPU;
 
 public:
   X86TargetInfo(const llvm::Triple &Triple)
@@ -1790,124 +1654,22 @@ public:
     return "";
   }
   virtual bool setCPU(const std::string &Name) {
-    CPU = llvm::StringSwitch<CPUKind>(Name)
-      .Case("i386", CK_i386)
-      .Case("i486", CK_i486)
-      .Case("winchip-c6", CK_WinChipC6)
-      .Case("winchip2", CK_WinChip2)
-      .Case("c3", CK_C3)
-      .Case("i586", CK_i586)
-      .Case("pentium", CK_Pentium)
-      .Case("pentium-mmx", CK_PentiumMMX)
-      .Case("i686", CK_i686)
-      .Case("pentiumpro", CK_PentiumPro)
-      .Case("pentium2", CK_Pentium2)
-      .Case("pentium3", CK_Pentium3)
-      .Case("pentium3m", CK_Pentium3M)
-      .Case("pentium-m", CK_PentiumM)
-      .Case("c3-2", CK_C3_2)
-      .Case("yonah", CK_Yonah)
-      .Case("pentium4", CK_Pentium4)
-      .Case("pentium4m", CK_Pentium4M)
-      .Case("prescott", CK_Prescott)
-      .Case("nocona", CK_Nocona)
-      .Case("core2", CK_Core2)
-      .Case("penryn", CK_Penryn)
-      .Case("atom", CK_Atom)
-      .Case("corei7", CK_Corei7)
-      .Case("corei7-avx", CK_Corei7AVX)
-      .Case("core-avx-i", CK_CoreAVXi)
-      .Case("core-avx2", CK_CoreAVX2)
-      .Case("k6", CK_K6)
-      .Case("k6-2", CK_K6_2)
-      .Case("k6-3", CK_K6_3)
-      .Case("athlon", CK_Athlon)
-      .Case("athlon-tbird", CK_AthlonThunderbird)
-      .Case("athlon-4", CK_Athlon4)
-      .Case("athlon-xp", CK_AthlonXP)
-      .Case("athlon-mp", CK_AthlonMP)
-      .Case("athlon64", CK_Athlon64)
-      .Case("athlon64-sse3", CK_Athlon64SSE3)
-      .Case("athlon-fx", CK_AthlonFX)
-      .Case("k8", CK_K8)
-      .Case("k8-sse3", CK_K8SSE3)
-      .Case("opteron", CK_Opteron)
-      .Case("opteron-sse3", CK_OpteronSSE3)
-      .Case("amdfam10", CK_AMDFAM10)
-      .Case("btver1", CK_BTVER1)
-      .Case("btver2", CK_BTVER2)
-      .Case("bdver1", CK_BDVER1)
-      .Case("bdver2", CK_BDVER2)
-      .Case("x86-64", CK_x86_64)
-      .Case("geode", CK_Geode)
-      .Default(CK_Generic);
+    CPU = (X86CPUKind)getX86CPUFromName(Name);
 
     // Perform any per-CPU checks necessary to determine if this CPU is
     // acceptable.
     // FIXME: This results in terrible diagnostics. Clang just says the CPU is
     // invalid without explaining *why*.
-    switch (CPU) {
-    case CK_Generic:
-      // No processor selected!
-      return false;
 
-    case CK_i386:
-    case CK_i486:
-    case CK_WinChipC6:
-    case CK_WinChip2:
-    case CK_C3:
-    case CK_i586:
-    case CK_Pentium:
-    case CK_PentiumMMX:
-    case CK_i686:
-    case CK_PentiumPro:
-    case CK_Pentium2:
-    case CK_Pentium3:
-    case CK_Pentium3M:
-    case CK_PentiumM:
-    case CK_Yonah:
-    case CK_C3_2:
-    case CK_Pentium4:
-    case CK_Pentium4M:
-    case CK_Prescott:
-    case CK_K6:
-    case CK_K6_2:
-    case CK_K6_3:
-    case CK_Athlon:
-    case CK_AthlonThunderbird:
-    case CK_Athlon4:
-    case CK_AthlonXP:
-    case CK_AthlonMP:
-    case CK_Geode:
-      // Only accept certain architectures when compiling in 32-bit mode.
-      if (getTriple().getArch() != llvm::Triple::x86)
-        return false;
+    if (CPU == CK_Generic) // No processor selected!
+      return false;
 
-      // Fallthrough
-    case CK_Nocona:
-    case CK_Core2:
-    case CK_Penryn:
-    case CK_Atom:
-    case CK_Corei7:
-    case CK_Corei7AVX:
-    case CK_CoreAVXi:
-    case CK_CoreAVX2:
-    case CK_Athlon64:
-    case CK_Athlon64SSE3:
-    case CK_AthlonFX:
-    case CK_K8:
-    case CK_K8SSE3:
-    case CK_Opteron:
-    case CK_OpteronSSE3:
-    case CK_AMDFAM10:
-    case CK_BTVER1:
-    case CK_BTVER2:
-    case CK_BDVER1:
-    case CK_BDVER2:
-    case CK_x86_64:
+    if (has64bits(CPU))
       return true;
-    }
-    llvm_unreachable("Unhandled CPU kind");
+
+    if (getTriple().getArch() != llvm::Triple::x86)
+      return false;
+    return true;
   }
 
   virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
@@ -1962,25 +1724,25 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
 
   switch (CPU) {
   case CK_Generic:
-  case CK_i386:
-  case CK_i486:
-  case CK_i586:
+  case CK_I386:
+  case CK_I486:
+  case CK_I586:
   case CK_Pentium:
-  case CK_i686:
-  case CK_PentiumPro:
+  case CK_I686:
+  case CK_Pentiumpro:
     break;
-  case CK_PentiumMMX:
+  case CK_Pentium_mmx:
   case CK_Pentium2:
     setFeatureEnabled(Features, "mmx", true);
     break;
   case CK_Pentium3:
-  case CK_Pentium3M:
+  case CK_Pentium3m:
     setFeatureEnabled(Features, "sse", true);
     break;
-  case CK_PentiumM:
+  case CK_Pentium_m:
   case CK_Pentium4:
-  case CK_Pentium4M:
-  case CK_x86_64:
+  case CK_Pentium4m:
+  case CK_X86_64:
     setFeatureEnabled(Features, "sse2", true);
     break;
   case CK_Yonah:
@@ -2000,19 +1762,19 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
   case CK_Corei7:
     setFeatureEnabled(Features, "sse4", true);
     break;
-  case CK_Corei7AVX:
+  case CK_Corei7_avx:
     setFeatureEnabled(Features, "avx", true);
     setFeatureEnabled(Features, "aes", true);
     setFeatureEnabled(Features, "pclmul", true);
     break;
-  case CK_CoreAVXi:
+  case CK_Core_avx_i:
     setFeatureEnabled(Features, "avx", true);
     setFeatureEnabled(Features, "aes", true);
     setFeatureEnabled(Features, "pclmul", true);
     setFeatureEnabled(Features, "rdrnd", true);
     setFeatureEnabled(Features, "f16c", true);
     break;
-  case CK_CoreAVX2:
+  case CK_Core_avx2:
     setFeatureEnabled(Features, "avx2", true);
     setFeatureEnabled(Features, "aes", true);
     setFeatureEnabled(Features, "pclmul", true);
@@ -2025,53 +1787,53 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
     setFeatureEnabled(Features, "fma", true);
     break;
   case CK_K6:
-  case CK_WinChipC6:
+  case CK_Winchip_c6:
     setFeatureEnabled(Features, "mmx", true);
     break;
   case CK_K6_2:
   case CK_K6_3:
-  case CK_WinChip2:
+  case CK_Winchip2:
   case CK_C3:
     setFeatureEnabled(Features, "3dnow", true);
     break;
   case CK_Athlon:
-  case CK_AthlonThunderbird:
+  case CK_Athlon_tbird:
   case CK_Geode:
     setFeatureEnabled(Features, "3dnowa", true);
     break;
-  case CK_Athlon4:
-  case CK_AthlonXP:
-  case CK_AthlonMP:
+  case CK_Athlon_4:
+  case CK_Athlon_xp:
+  case CK_Athlon_mp:
     setFeatureEnabled(Features, "sse", true);
     setFeatureEnabled(Features, "3dnowa", true);
     break;
   case CK_K8:
   case CK_Opteron:
   case CK_Athlon64:
-  case CK_AthlonFX:
+  case CK_Athlon_fx:
     setFeatureEnabled(Features, "sse2", true);
     setFeatureEnabled(Features, "3dnowa", true);
     break;
-  case CK_K8SSE3:
-  case CK_OpteronSSE3:
-  case CK_Athlon64SSE3:
+  case CK_K8_sse3:
+  case CK_Opteron_sse3:
+  case CK_Athlon64_sse3:
     setFeatureEnabled(Features, "sse3", true);
     setFeatureEnabled(Features, "3dnowa", true);
     break;
-  case CK_AMDFAM10:
+  case CK_Amdfam10:
     setFeatureEnabled(Features, "sse3", true);
     setFeatureEnabled(Features, "sse4a", true);
     setFeatureEnabled(Features, "3dnowa", true);
     setFeatureEnabled(Features, "lzcnt", true);
     setFeatureEnabled(Features, "popcnt", true);
     break;
-  case CK_BTVER1:
+  case CK_Btver1:
     setFeatureEnabled(Features, "ssse3", true);
     setFeatureEnabled(Features, "sse4a", true);
     setFeatureEnabled(Features, "lzcnt", true);
     setFeatureEnabled(Features, "popcnt", true);
     break;
-  case CK_BTVER2:
+  case CK_Btver2:
     setFeatureEnabled(Features, "avx", true);
     setFeatureEnabled(Features, "sse4a", true);
     setFeatureEnabled(Features, "lzcnt", true);
@@ -2080,13 +1842,13 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
     setFeatureEnabled(Features, "bmi", true);
     setFeatureEnabled(Features, "f16c", true);
     break;
-  case CK_BDVER1:
+  case CK_Bdver1:
     setFeatureEnabled(Features, "xop", true);
     setFeatureEnabled(Features, "lzcnt", true);
     setFeatureEnabled(Features, "aes", true);
     setFeatureEnabled(Features, "pclmul", true);
     break;
-  case CK_BDVER2:
+  case CK_Bdver2:
     setFeatureEnabled(Features, "xop", true);
     setFeatureEnabled(Features, "lzcnt", true);
     setFeatureEnabled(Features, "aes", true);
@@ -2394,39 +2156,39 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
   switch (CPU) {
   case CK_Generic:
     break;
-  case CK_i386:
+  case CK_I386:
     // The rest are coming from the i386 define above.
     Builder.defineMacro("__tune_i386__");
     break;
-  case CK_i486:
-  case CK_WinChipC6:
-  case CK_WinChip2:
+  case CK_I486:
+  case CK_Winchip_c6:
+  case CK_Winchip2:
   case CK_C3:
     defineCPUMacros(Builder, "i486");
     break;
-  case CK_PentiumMMX:
+  case CK_Pentium_mmx:
     Builder.defineMacro("__pentium_mmx__");
     Builder.defineMacro("__tune_pentium_mmx__");
     // Fallthrough
-  case CK_i586:
+  case CK_I586:
   case CK_Pentium:
     defineCPUMacros(Builder, "i586");
     defineCPUMacros(Builder, "pentium");
     break;
   case CK_Pentium3:
-  case CK_Pentium3M:
-  case CK_PentiumM:
+  case CK_Pentium3m:
+  case CK_Pentium_m:
     Builder.defineMacro("__tune_pentium3__");
     // Fallthrough
   case CK_Pentium2:
   case CK_C3_2:
     Builder.defineMacro("__tune_pentium2__");
     // Fallthrough
-  case CK_PentiumPro:
+  case CK_Pentiumpro:
     Builder.defineMacro("__tune_i686__");
     Builder.defineMacro("__tune_pentiumpro__");
     // Fallthrough
-  case CK_i686:
+  case CK_I686:
     Builder.defineMacro("__i686");
     Builder.defineMacro("__i686__");
     // Strangely, __tune_i686__ isn't defined by GCC when CPU == i686.
@@ -2434,7 +2196,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__pentiumpro__");
     break;
   case CK_Pentium4:
-  case CK_Pentium4M:
+  case CK_Pentium4m:
     defineCPUMacros(Builder, "pentium4");
     break;
   case CK_Yonah:
@@ -2450,9 +2212,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     defineCPUMacros(Builder, "atom");
     break;
   case CK_Corei7:
-  case CK_Corei7AVX:
-  case CK_CoreAVXi:
-  case CK_CoreAVX2:
+  case CK_Corei7_avx:
+  case CK_Core_avx_i:
+  case CK_Core_avx2:
     defineCPUMacros(Builder, "corei7");
     break;
   case CK_K6_2:
@@ -2472,10 +2234,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     defineCPUMacros(Builder, "k6");
     break;
   case CK_Athlon:
-  case CK_AthlonThunderbird:
-  case CK_Athlon4:
-  case CK_AthlonXP:
-  case CK_AthlonMP:
+  case CK_Athlon_tbird:
+  case CK_Athlon_4:
+  case CK_Athlon_xp:
+  case CK_Athlon_mp:
     defineCPUMacros(Builder, "athlon");
     if (SSELevel != NoSSE) {
       Builder.defineMacro("__athlon_sse__");
@@ -2483,28 +2245,28 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     }
     break;
   case CK_K8:
-  case CK_K8SSE3:
-  case CK_x86_64:
+  case CK_K8_sse3:
+  case CK_X86_64:
   case CK_Opteron:
-  case CK_OpteronSSE3:
+  case CK_Opteron_sse3:
   case CK_Athlon64:
-  case CK_Athlon64SSE3:
-  case CK_AthlonFX:
+  case CK_Athlon64_sse3:
+  case CK_Athlon_fx:
     defineCPUMacros(Builder, "k8");
     break;
-  case CK_AMDFAM10:
+  case CK_Amdfam10:
     defineCPUMacros(Builder, "amdfam10");
     break;
-  case CK_BTVER1:
+  case CK_Btver1:
     defineCPUMacros(Builder, "btver1");
     break;
-  case CK_BTVER2:
+  case CK_Btver2:
     defineCPUMacros(Builder, "btver2");
     break;
-  case CK_BDVER1:
+  case CK_Bdver1:
     defineCPUMacros(Builder, "bdver1");
     break;
-  case CK_BDVER2:
+  case CK_Bdver2:
     defineCPUMacros(Builder, "bdver2");
     break;
   case CK_Geode:
@@ -2621,12 +2383,12 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     break;
   }
 
-  if (CPU >= CK_i486) {
+  if (CPU >= CK_I486) {
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
   }
-  if (CPU >= CK_i586)
+  if (CPU >= CK_I586)
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
 }
 
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 9768352..fdb21f1 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -12,7 +12,9 @@
 #include "SanitizerArgs.h"
 #include "ToolChains.h"
 #include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
+#include "clang/Basic/X86CPUNamesEnum.inc"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
@@ -1255,11 +1257,11 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args,
   CmdArgs.push_back(CPUName);
 }
 
-static const char *getX86TargetCPU(const ArgList &Args,
-                                   const llvm::Triple &Triple) {
+static X86CPUKind getX86TargetCPU(const ArgList &Args,
+                                  const llvm::Triple &Triple) {
   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
     if (StringRef(A->getValue()) != "native")
-      return A->getValue();
+      return (X86CPUKind)getX86CPUFromName(A->getValue());
 
     // FIXME: Reject attempts to use -march=native unless the target matches
     // the host.
@@ -1268,42 +1270,40 @@ static const char *getX86TargetCPU(const ArgList &Args,
     // with -native.
     std::string CPU = llvm::sys::getHostCPUName();
     if (!CPU.empty() && CPU != "generic")
-      return Args.MakeArgString(CPU);
+      return (X86CPUKind)getX86CPUFromName(CPU);
   }
 
   // Select the default CPU if none was given (or detection failed).
 
-  if (Triple.getArch() != llvm::Triple::x86_64 &&
-      Triple.getArch() != llvm::Triple::x86)
-    return 0; // This routine is only handling x86 targets.
-
+  assert(Triple.getArch() == llvm::Triple::x86_64 ||
+         Triple.getArch() == llvm::Triple::x86);
   bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
 
   // FIXME: Need target hooks.
   if (Triple.isOSDarwin())
-    return Is64Bit ? "core2" : "yonah";
+    return Is64Bit ? CK_Core2 : CK_Yonah;
 
   // Everything else goes to x86-64 in 64-bit mode.
   if (Is64Bit)
-    return "x86-64";
+    return CK_X86_64;
 
   if (Triple.getOSName().startswith("haiku"))
-    return "i586";
+    return CK_I586;
   if (Triple.getOSName().startswith("openbsd"))
-    return "i486";
+    return CK_I486;
   if (Triple.getOSName().startswith("bitrig"))
-    return "i686";
+    return CK_I686;
   if (Triple.getOSName().startswith("freebsd"))
-    return "i486";
+    return CK_I486;
   if (Triple.getOSName().startswith("netbsd"))
-    return "i486";
+    return CK_I486;
   // All x86 devices running Android have core2 as their common
   // denominator. This makes a better choice than pentium4.
   if (Triple.getEnvironment() == llvm::Triple::Android)
-    return "core2";
+    return CK_Core2;
 
   // Fallback to p4.
-  return "pentium4";
+  return CK_Pentium4;
 }
 
 void Clang::AddX86TargetArgs(const ArgList &Args,
@@ -1330,10 +1330,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
   if (NoImplicitFloat)
     CmdArgs.push_back("-no-implicit-float");
 
-  if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
-    CmdArgs.push_back("-target-cpu");
-    CmdArgs.push_back(CPUName);
-  }
+  X86CPUKind CPU = getX86TargetCPU(Args, getToolChain().getTriple());
+  CmdArgs.push_back("-target-cpu");
+  const char *CPUName = getX86CPUName(CPU);
+  CmdArgs.push_back(CPUName);
 
   // The required algorithm here is slightly strange: the options are applied
   // in order (so -mno-sse -msse2 disables SSE3), but any option that gets
@@ -3583,10 +3583,9 @@ void ClangAs::AddARMTargetArgs(const ArgList &Args,
 void ClangAs::AddX86TargetArgs(const ArgList &Args,
                                ArgStringList &CmdArgs) const {
   // Set the CPU based on -march=.
-  if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
-    CmdArgs.push_back("-target-cpu");
-    CmdArgs.push_back(CPUName);
-  }
+  X86CPUKind CPU = getX86TargetCPU(Args, getToolChain().getTriple());
+  CmdArgs.push_back("-target-cpu");
+  CmdArgs.push_back(getX86CPUName(CPU));
 }
 
 /// Add options related to the Objective-C runtime/ABI.
@@ -6208,9 +6207,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
     // Handle architecture-specific flags for selecting CPU variants.
     if (ToolChain.getArch() == llvm::Triple::x86 ||
         ToolChain.getArch() == llvm::Triple::x86_64)
-      CmdArgs.push_back(
-          Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
-                             getX86TargetCPU(Args, ToolChain.getTriple())));
+      CmdArgs.push_back(Args.MakeArgString(
+          Twine("-plugin-opt=mcpu=") +
+          getX86CPUName(getX86TargetCPU(Args, ToolChain.getTriple()))));
     else if (ToolChain.getArch() == llvm::Triple::arm ||
              ToolChain.getArch() == llvm::Triple::thumb)
       CmdArgs.push_back(
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 29a1eed..19e7e51 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -10,4 +10,5 @@ add_tablegen(clang-tblgen CLANG
   ClangSACheckersEmitter.cpp
   NeonEmitter.cpp
   TableGen.cpp
+  ClangX86CPUNamesEmitter.cpp
   )
diff --git a/utils/TableGen/ClangX86CPUNamesEmitter.cpp b/utils/TableGen/ClangX86CPUNamesEmitter.cpp
new file mode 100644
index 0000000..c133c75
--- /dev/null
+++ b/utils/TableGen/ClangX86CPUNamesEmitter.cpp
@@ -0,0 +1,109 @@
+//===--- ClangX86CPUNamesEmitter.cpp ----------------------------------------=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits an enum for x86 cpus and functions for converting
+// to and from strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h"
+#include "llvm/TableGen/Record.h"
+
+#include <vector>
+
+using namespace llvm;
+
+static char ascii_toupper(char x) {
+  if (x >= 'a' && x <= 'z')
+    return x - 'a' + 'A';
+  return x;
+}
+
+static void printEnumName(StringRef CPUName, raw_ostream &OS) {
+  assert(!CPUName.empty());
+  OS << ascii_toupper(CPUName[0]);
+  for (int I = 1, N = CPUName.size(); I < N; ++I) {
+    char C = CPUName[I];
+    if (C == '-')
+      OS << '_';
+    else
+      OS << C;
+  }
+}
+
+namespace clang {
+void EmitClangX86CPUNamesEnum(RecordKeeper &Records, raw_ostream &OS) {
+  std::vector<Record *> CPUs = Records.getAllDerivedDefinitions("X86CPU");
+  OS << "namespace clang {\n";
+
+  OS << "enum X86CPUKind {\n";
+  for (std::vector<Record *>::iterator I = CPUs.begin(), E = CPUs.end(),
+                                       B = E - 1;
+       I != E; ++I) {
+    Record &CPU = **I;
+    OS << "  CK_";
+    printEnumName(CPU.getValueAsString("Name"), OS);
+
+    if (I != B)
+      OS << ",";
+    OS << "\n";
+  }
+  OS << "};\n";
+  OS << "}\n";
+}
+
+void EmitClangX86CPUNamesFuncs(RecordKeeper &Records, raw_ostream &OS) {
+  std::vector<Record *> CPUs = Records.getAllDerivedDefinitions("X86CPU");
+  OS << "namespace clang {\n";
+
+  OS << "const char *getX86CPUName(int C) {\n";
+  OS << "  X86CPUKind CPU = (X86CPUKind)C;\n";
+  OS << "  switch (CPU) {\n";
+  for (std::vector<Record *>::iterator I = CPUs.begin(), E = CPUs.end(); I != E;
+       ++I) {
+    Record &CPU = **I;
+    std::string Name = CPU.getValueAsString("Name");
+    OS << "    case CK_";
+    printEnumName(Name, OS);
+    OS << ":\n";
+    OS << "      return \"" << Name << "\";\n";
+  }
+  OS << "  }\n";
+  OS << "}\n";
+
+  OS << "int getX86CPUFromName(StringRef Name) {\n";
+  OS << "  return llvm::StringSwitch<X86CPUKind>(Name)\n";
+  for (std::vector<Record *>::iterator I = CPUs.begin(), E = CPUs.end(); I != E;
+       ++I) {
+    Record &CPU = **I;
+    std::string Name = CPU.getValueAsString("Name");
+    OS << "      .Case(\"" << Name << "\", CK_";
+    printEnumName(Name, OS);
+    OS << ")\n";
+  }
+  OS << "      .Default(CK_Generic);\n";
+  OS << "}\n";
+
+  OS << "static bool has64bits(int C) {\n";
+  OS << "  X86CPUKind CPU = (X86CPUKind)C;\n";
+  OS << "  switch (CPU) {\n";
+  for (std::vector<Record *>::iterator I = CPUs.begin(), E = CPUs.end(); I != E;
+       ++I) {
+    Record &CPU = **I;
+    OS << "  case CK_";
+    printEnumName(CPU.getValueAsString("Name"), OS);
+    OS << ":\n";
+    OS << "    return " << CPU.getValueAsBit("Has64Bits") << ";\n";
+  }
+  OS << "}\n";
+  OS << "}\n";
+
+  OS << "}\n";
+}
+}
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 429b6fb..56631bb 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -50,7 +50,9 @@ enum ActionType {
   GenClangCommentCommandList,
   GenArmNeon,
   GenArmNeonSema,
-  GenArmNeonTest
+  GenArmNeonTest,
+  GenClangX86CPUNamesEnum,
+  GenClangX86CPUNamesFuncs,
 };
 
 namespace {
@@ -125,6 +127,10 @@ cl::opt<ActionType> Action(
                    "Generate ARM NEON sema support for clang"),
         clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
                    "Generate ARM NEON tests for clang"),
+        clEnumValN(GenClangX86CPUNamesEnum, "gen-clang-x86-cpu-names-enum",
+                   "Generate enum with x86 cpu names"),
+        clEnumValN(GenClangX86CPUNamesFuncs, "gen-clang-x86-cpu-names-funcs",
+                   "Generate helper functions for x86 cpus"),
         clEnumValEnd));
 
 cl::opt<std::string>
@@ -219,6 +225,12 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
   case GenArmNeonTest:
     EmitNeonTest(Records, OS);
     break;
+  case GenClangX86CPUNamesEnum:
+    EmitClangX86CPUNamesEnum(Records, OS);
+    break;
+  case GenClangX86CPUNamesFuncs:
+    EmitClangX86CPUNamesFuncs(Records, OS);
+    break;
   }
 
   return false;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index b641732..6ebf8eb 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -61,4 +61,6 @@ void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
 void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
 void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
 
+void EmitClangX86CPUNamesEnum(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangX86CPUNamesFuncs(RecordKeeper &Records, raw_ostream &OS);
 } // end namespace clang
