[X86] Add a helper lambda to getIntelProcessorTypeAndSubtype to select feature bits...
authorCraig Topper <craig.topper@intel.com>
Fri, 12 Jun 2020 04:14:45 +0000 (21:14 -0700)
committerCraig Topper <craig.topper@intel.com>
Fri, 12 Jun 2020 04:14:46 +0000 (21:14 -0700)
We have three 32 bit variables containing feature bits. But our
enum is a flat 96 bit space. So we need to pick which of the
variables to use based on the bit value. We used to do this
manually by mentioning the correct variable and subtracting an
offset from the enum. But this is error prone.

llvm/lib/Support/Host.cpp

index 930abc3..be46a53 100644 (file)
@@ -585,6 +585,16 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
                                 unsigned Brand_id, unsigned Features,
                                 unsigned Features2, unsigned Features3,
                                 unsigned *Type, unsigned *Subtype) {
+  auto testFeature = [&](unsigned F) {
+    if (F < 32)
+      return (Features & (1U << (F & 0x1f))) != 0;
+    if (F < 64)
+      return (Features2 & (1U << ((F - 32) & 0x1f))) != 0;
+    if (F < 96)
+      return (Features3 & (1U << ((F - 64) & 0x1f))) != 0;
+    llvm_unreachable("Unexpected FeatureBit");
+  };
+
   if (Brand_id != 0)
     return;
   switch (Family) {
@@ -595,7 +605,7 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
     *Type = X86::INTEL_i486;
     break;
   case 5:
-    if (Features & (1 << X86::FEATURE_MMX)) {
+    if (testFeature(X86::FEATURE_MMX)) {
       *Type = X86::INTEL_PENTIUM_MMX;
       break;
     }
@@ -711,9 +721,9 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
     // Skylake Xeon:
     case 0x55:
       *Type = X86::INTEL_COREI7;
-      if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32)))
+      if (testFeature(X86::FEATURE_AVX512BF16))
         *Subtype = X86::INTEL_COREI7_COOPERLAKE; // "cooperlake"
-      else if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32)))
+      else if (testFeature(X86::FEATURE_AVX512VNNI))
         *Subtype = X86::INTEL_COREI7_CASCADELAKE; // "cascadelake"
       else
         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512"
@@ -777,50 +787,50 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
       break;
 
     default: // Unknown family 6 CPU, try to guess.
-      // TODO detect tigerlake host
-      if (Features2 & (1 << (X86::FEATURE_AVX512VP2INTERSECT - 32))) {
+      // TODO detect tigerlake host from model
+      if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_TIGERLAKE;
         break;
       }
 
-      if (Features & (1 << X86::FEATURE_AVX512VBMI2)) {
+      if (testFeature(X86::FEATURE_AVX512VBMI2)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
         break;
       }
 
-      if (Features & (1 << X86::FEATURE_AVX512VBMI)) {
+      if (testFeature(X86::FEATURE_AVX512VBMI)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_CANNONLAKE;
         break;
       }
 
-      if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32))) {
+      if (testFeature(X86::FEATURE_AVX512BF16)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_COOPERLAKE;
         break;
       }
 
-      if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32))) {
+      if (testFeature(X86::FEATURE_AVX512VNNI)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_CASCADELAKE;
         break;
       }
 
-      if (Features & (1 << X86::FEATURE_AVX512VL)) {
+      if (testFeature(X86::FEATURE_AVX512VL)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
         break;
       }
 
-      if (Features & (1 << X86::FEATURE_AVX512ER)) {
+      if (testFeature(X86::FEATURE_AVX512ER)) {
         *Type = X86::INTEL_KNL; // knl
         break;
       }
 
-      if (Features3 & (1 << (X86::FEATURE_CLFLUSHOPT - 64))) {
-        if (Features3 & (1 << (X86::FEATURE_SHA - 64))) {
+      if (testFeature(X86::FEATURE_CLFLUSHOPT)) {
+        if (testFeature(X86::FEATURE_SHA)) {
           *Type = X86::INTEL_GOLDMONT;
         } else {
           *Type = X86::INTEL_COREI7;
@@ -828,23 +838,23 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
         }
         break;
       }
-      if (Features3 & (1 << (X86::FEATURE_ADX - 64))) {
+      if (testFeature(X86::FEATURE_ADX)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_BROADWELL;
         break;
       }
-      if (Features & (1 << X86::FEATURE_AVX2)) {
+      if (testFeature(X86::FEATURE_AVX2)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_HASWELL;
         break;
       }
-      if (Features & (1 << X86::FEATURE_AVX)) {
+      if (testFeature(X86::FEATURE_AVX)) {
         *Type = X86::INTEL_COREI7;
         *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSE4_2)) {
-        if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
+      if (testFeature(X86::FEATURE_SSE4_2)) {
+        if (testFeature(X86::FEATURE_MOVBE)) {
           *Type = X86::INTEL_SILVERMONT;
         } else {
           *Type = X86::INTEL_COREI7;
@@ -852,13 +862,13 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
         }
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSE4_1)) {
+      if (testFeature(X86::FEATURE_SSE4_1)) {
         *Type = X86::INTEL_CORE2; // "penryn"
         *Subtype = X86::INTEL_CORE2_45;
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSSE3)) {
-        if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
+      if (testFeature(X86::FEATURE_SSSE3)) {
+        if (testFeature(X86::FEATURE_MOVBE)) {
           *Type = X86::INTEL_BONNELL; // "bonnell"
         } else {
           *Type = X86::INTEL_CORE2; // "core2"
@@ -866,24 +876,24 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
         }
         break;
       }
-      if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
+      if (testFeature(X86::FEATURE_EM64T)) {
         *Type = X86::INTEL_CORE2; // "core2"
         *Subtype = X86::INTEL_CORE2_65;
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSE3)) {
+      if (testFeature(X86::FEATURE_SSE3)) {
         *Type = X86::INTEL_CORE_DUO;
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSE2)) {
+      if (testFeature(X86::FEATURE_SSE2)) {
         *Type = X86::INTEL_PENTIUM_M;
         break;
       }
-      if (Features & (1 << X86::FEATURE_SSE)) {
+      if (testFeature(X86::FEATURE_SSE)) {
         *Type = X86::INTEL_PENTIUM_III;
         break;
       }
-      if (Features & (1 << X86::FEATURE_MMX)) {
+      if (testFeature(X86::FEATURE_MMX)) {
         *Type = X86::INTEL_PENTIUM_II;
         break;
       }
@@ -892,11 +902,11 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
     }
     break;
   case 15: {
-    if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
+    if (testFeature(X86::FEATURE_EM64T)) {
       *Type = X86::INTEL_NOCONA;
       break;
     }
-    if (Features & (1 << X86::FEATURE_SSE3)) {
+    if (testFeature(X86::FEATURE_SSE3)) {
       *Type = X86::INTEL_PRESCOTT;
       break;
     }
@@ -911,6 +921,12 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
 static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
                                           unsigned Features, unsigned *Type,
                                           unsigned *Subtype) {
+  auto testFeature = [&](unsigned F) {
+    if (F < 32)
+      return (Features & (1U << (F & 0x1f))) != 0;
+    llvm_unreachable("Unexpected FeatureBit");
+  };
+
   // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
   // appears to be no way to generate the wide variety of AMD-specific targets
   // from the information returned from CPUID.
@@ -938,14 +954,14 @@ static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
     }
     break;
   case 6:
-    if (Features & (1 << X86::FEATURE_SSE)) {
+    if (testFeature(X86::FEATURE_SSE)) {
       *Type = X86::AMD_ATHLON_XP;
       break; // "athlon-xp"
     }
     *Type = X86::AMD_ATHLON;
     break; // "athlon"
   case 15:
-    if (Features & (1 << X86::FEATURE_SSE3)) {
+    if (testFeature(X86::FEATURE_SSE3)) {
       *Type = X86::AMD_K8SSE3;
       break; // "k8-sse3"
     }