[X86][compiler-rt] Add additional CPUs and features to the cpu detection to match libgcc
Summary: This patch adds additional features and cpus from libgcc. Unfortunately we've overflowed the existing 32-bits of features so we had to add a new __cpu_features2 variable to hold the additional bits. This matches libgcc as far as I can tell.
Reviewers: echristo
Reviewed By: echristo
Subscribers: dberris, llvm-commits
Differential Revision: https://reviews.llvm.org/D53461
llvm-svn: 344830
diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c
index 43b9133..54f1add 100644
--- a/compiler-rt/lib/builtins/cpu_model.c
+++ b/compiler-rt/lib/builtins/cpu_model.c
@@ -55,6 +55,9 @@
AMD_BTVER2,
AMDFAM17H,
INTEL_KNM,
+ INTEL_GOLDMONT,
+ INTEL_GOLDMONT_PLUS,
+ INTEL_TREMONT,
CPU_TYPE_MAX
};
@@ -76,6 +79,8 @@
INTEL_COREI7_SKYLAKE,
INTEL_COREI7_SKYLAKE_AVX512,
INTEL_COREI7_CANNONLAKE,
+ INTEL_COREI7_ICELAKE_CLIENT,
+ INTEL_COREI7_ICELAKE_SERVER,
CPU_SUBTYPE_MAX
};
@@ -110,7 +115,12 @@
FEATURE_AVX512IFMA,
FEATURE_AVX5124VNNIW,
FEATURE_AVX5124FMAPS,
- FEATURE_AVX512VPOPCNTDQ
+ FEATURE_AVX512VPOPCNTDQ,
+ FEATURE_AVX512VBMI2,
+ FEATURE_GFNI,
+ FEATURE_VPCLMULQDQ,
+ FEATURE_AVX512VNNI,
+ FEATURE_AVX512BITALG
};
// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
@@ -364,6 +374,14 @@
case 0x4c: // really airmont
*Type = INTEL_SILVERMONT;
break; // "silvermont"
+ // Goldmont:
+ case 0x5c: // Apollo Lake
+ case 0x5f: // Denverton
+ *Type = INTEL_GOLDMONT;
+ break; // "goldmont"
+ case 0x7a:
+ *Type = INTEL_GOLDMONT_PLUS;
+ break;
case 0x57:
*Type = INTEL_KNL; // knl
@@ -438,35 +456,45 @@
}
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
- unsigned *FeaturesOut) {
+ unsigned *FeaturesOut,
+ unsigned *Features2Out) {
unsigned Features = 0;
+ unsigned Features2 = 0;
unsigned EAX, EBX;
+#define setFeature(F) \
+ do { \
+ if (F < 32) \
+ Features |= 1 << F; \
+ else if (F < 64) \
+ Features2 |= 1 << (F - 32); \
+ } while (0)
+
if ((EDX >> 15) & 1)
- Features |= 1 << FEATURE_CMOV;
+ setFeature(FEATURE_CMOV);
if ((EDX >> 23) & 1)
- Features |= 1 << FEATURE_MMX;
+ setFeature(FEATURE_MMX);
if ((EDX >> 25) & 1)
- Features |= 1 << FEATURE_SSE;
+ setFeature(FEATURE_SSE);
if ((EDX >> 26) & 1)
- Features |= 1 << FEATURE_SSE2;
+ setFeature(FEATURE_SSE2);
if ((ECX >> 0) & 1)
- Features |= 1 << FEATURE_SSE3;
+ setFeature(FEATURE_SSE3);
if ((ECX >> 1) & 1)
- Features |= 1 << FEATURE_PCLMUL;
+ setFeature(FEATURE_PCLMUL);
if ((ECX >> 9) & 1)
- Features |= 1 << FEATURE_SSSE3;
+ setFeature(FEATURE_SSSE3);
if ((ECX >> 12) & 1)
- Features |= 1 << FEATURE_FMA;
+ setFeature(FEATURE_FMA);
if ((ECX >> 19) & 1)
- Features |= 1 << FEATURE_SSE4_1;
+ setFeature(FEATURE_SSE4_1);
if ((ECX >> 20) & 1)
- Features |= 1 << FEATURE_SSE4_2;
+ setFeature(FEATURE_SSE4_2);
if ((ECX >> 23) & 1)
- Features |= 1 << FEATURE_POPCNT;
+ setFeature(FEATURE_POPCNT);
if ((ECX >> 25) & 1)
- Features |= 1 << FEATURE_AES;
+ setFeature(FEATURE_AES);
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
@@ -477,43 +505,53 @@
bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
if (HasAVX)
- Features |= 1 << FEATURE_AVX;
+ setFeature(FEATURE_AVX);
bool HasLeaf7 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7 && ((EBX >> 3) & 1))
- Features |= 1 << FEATURE_BMI;
+ setFeature(FEATURE_BMI);
if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
- Features |= 1 << FEATURE_AVX2;
+ setFeature(FEATURE_AVX2);
if (HasLeaf7 && ((EBX >> 9) & 1))
- Features |= 1 << FEATURE_BMI2;
+ setFeature(FEATURE_BMI2);
if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512F;
+ setFeature(FEATURE_AVX512F);
if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512DQ;
+ setFeature(FEATURE_AVX512DQ);
if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512IFMA;
+ setFeature(FEATURE_AVX512IFMA);
if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512PF;
+ setFeature(FEATURE_AVX512PF);
if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512ER;
+ setFeature(FEATURE_AVX512ER);
if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512CD;
+ setFeature(FEATURE_AVX512CD);
if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512BW;
+ setFeature(FEATURE_AVX512BW);
if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512VL;
+ setFeature(FEATURE_AVX512VL);
if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512VBMI;
+ setFeature(FEATURE_AVX512VBMI);
+ if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
+ setFeature(FEATURE_AVX512VBMI2);
+ if (HasLeaf7 && ((ECX >> 8) & 1))
+ setFeature(FEATURE_GFNI);
+ if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
+ setFeature(FEATURE_VPCLMULQDQ);
+ if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
+ setFeature(FEATURE_AVX512VNNI);
+ if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
+ setFeature(FEATURE_AVX512BITALG);
if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX512VPOPCNTDQ;
+ setFeature(FEATURE_AVX512VPOPCNTDQ);
if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX5124VNNIW;
+ setFeature(FEATURE_AVX5124VNNIW);
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
- Features |= 1 << FEATURE_AVX5124FMAPS;
+ setFeature(FEATURE_AVX5124FMAPS);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
@@ -521,13 +559,15 @@
bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
if (HasExtLeaf1 && ((ECX >> 6) & 1))
- Features |= 1 << FEATURE_SSE4_A;
+ setFeature(FEATURE_SSE4_A);
if (HasExtLeaf1 && ((ECX >> 11) & 1))
- Features |= 1 << FEATURE_XOP;
+ setFeature(FEATURE_XOP);
if (HasExtLeaf1 && ((ECX >> 16) & 1))
- Features |= 1 << FEATURE_FMA4;
+ setFeature(FEATURE_FMA4);
*FeaturesOut = Features;
+ *Features2Out = Features2;
+#undef setFeature
}
#if defined(HAVE_INIT_PRIORITY)
@@ -548,8 +588,9 @@
unsigned int __cpu_subtype;
unsigned int __cpu_features[1];
} __cpu_model = {0, 0, 0, {0}};
+unsigned int __cpu_features2;
-/* A constructor function that is sets __cpu_model and __cpu_features with
+/* A constructor function that is sets __cpu_model and __cpu_features2 with
the right values. This needs to run only once. This constructor is
given the highest priority and it should run before constructors without
the priority set. However, it still runs after ifunc initializers and
@@ -562,6 +603,7 @@
unsigned Vendor;
unsigned Model, Family, Brand_id;
unsigned Features = 0;
+ unsigned Features2 = 0;
/* This function needs to run just once. */
if (__cpu_model.__cpu_vendor)
@@ -580,8 +622,9 @@
Brand_id = EBX & 0xff;
/* Find available features. */
- getAvailableFeatures(ECX, EDX, MaxLeaf, &Features);
+ getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2);
__cpu_model.__cpu_features[0] = Features;
+ __cpu_features2 = Features2;
if (Vendor == SIG_INTEL) {
/* Get CPU type. */