19 #include "llvm/Config/config.h"
35 #if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
36 #include <mach/mach.h>
37 #include <mach/mach_host.h>
38 #include <mach/host_info.h>
39 #include <mach/machine.h>
42 #define DEBUG_TYPE "host-detection"
52 #if defined(__linux__)
61 DEBUG(
dbgs() <<
"Unable to open /proc/cpuinfo: " << EC.message() <<
"\n");
65 int CloseStatus = close(FD);
72 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
73 || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
77 static bool GetX86CpuIDAndInfo(
unsigned value,
unsigned *rEAX,
unsigned *rEBX,
78 unsigned *rECX,
unsigned *rEDX) {
79 #if defined(__GNUC__) || defined(__clang__)
80 #if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
82 asm (
"movq\t%%rbx, %%rsi\n\t"
84 "xchgq\t%%rbx, %%rsi\n\t"
91 #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
92 asm (
"movl\t%%ebx, %%esi\n\t"
94 "xchgl\t%%ebx, %%esi\n\t"
106 #elif defined(_MSC_VER)
109 __cpuid(registers, value);
110 *rEAX = registers[0];
111 *rEBX = registers[1];
112 *rECX = registers[2];
113 *rEDX = registers[3];
123 static bool GetX86CpuIDAndInfoEx(
unsigned value,
unsigned subleaf,
124 unsigned *rEAX,
unsigned *rEBX,
unsigned *rECX,
126 #if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
127 #if defined(__GNUC__)
129 asm (
"movq\t%%rbx, %%rsi\n\t"
131 "xchgq\t%%rbx, %%rsi\n\t"
139 #elif defined(_MSC_VER)
141 __cpuidex(registers, value, subleaf);
142 *rEAX = registers[0];
143 *rEBX = registers[1];
144 *rECX = registers[2];
145 *rEDX = registers[3];
150 #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
151 #if defined(__GNUC__)
152 asm (
"movl\t%%ebx, %%esi\n\t"
154 "xchgl\t%%ebx, %%esi\n\t"
162 #elif defined(_MSC_VER)
168 mov dword ptr [esi],eax
170 mov dword ptr [esi],ebx
172 mov dword ptr [esi],ecx
174 mov dword ptr [esi],edx
185 static bool GetX86XCR0(
unsigned *rEAX,
unsigned *rEDX) {
186 #if defined(__GNUC__)
190 __asm__ (
".byte 0x0f, 0x01, 0xd0" :
"=a" (*rEAX),
"=d" (*rEDX) :
"c" (0));
192 #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
193 unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
195 *rEDX = Result >> 32;
202 static void DetectX86FamilyModel(
unsigned EAX,
unsigned &Family,
204 Family = (EAX >> 8) & 0xf;
205 Model = (EAX >> 4) & 0xf;
206 if (Family == 6 || Family == 0xf) {
209 Family += (EAX >> 20) & 0xff;
211 Model += ((EAX >> 16) & 0xf) << 4;
216 unsigned EAX = 0,
EBX = 0,
ECX = 0,
EDX = 0;
217 if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
221 DetectX86FamilyModel(EAX, Family, Model);
229 GetX86CpuIDAndInfo(0, &MaxLeaf, text.u+0, text.u+2, text.u+1);
231 bool HasMMX = (
EDX >> 23) & 1;
232 bool HasSSE = (
EDX >> 25) & 1;
233 bool HasSSE2 = (
EDX >> 26) & 1;
234 bool HasSSE3 = (
ECX >> 0) & 1;
235 bool HasSSSE3 = (
ECX >> 9) & 1;
236 bool HasSSE41 = (
ECX >> 19) & 1;
237 bool HasSSE42 = (
ECX >> 20) & 1;
238 bool HasMOVBE = (
ECX >> 22) & 1;
242 const unsigned AVXBits = (1 << 27) | (1 << 28);
243 bool HasAVX = ((
ECX & AVXBits) == AVXBits) && !GetX86XCR0(&EAX, &EDX) &&
244 ((EAX & 0x6) == 0x6);
245 bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
246 bool HasLeaf7 = MaxLeaf >= 0x7 &&
247 !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
248 bool HasADX = HasLeaf7 && ((
EBX >> 19) & 1);
249 bool HasAVX2 = HasAVX && HasLeaf7 && (
EBX & 0x20);
250 bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((
EBX >> 16) & 1);
252 GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
253 bool Em64T = (
EDX >> 29) & 0x1;
254 bool HasTBM = (
ECX >> 21) & 0x1;
256 if (memcmp(text.c,
"GenuineIntel", 12) == 0) {
271 default:
return "i486";
287 return "pentium-mmx";
289 default:
return "pentium";
355 return "sandybridge";
394 return "sandybridge";
396 return HasMOVBE ?
"silvermont" :
"nehalem";
400 return HasMOVBE ?
"bonnell" :
"core2";
422 return (Em64T) ?
"x86-64" :
"pentium4";
435 return (Em64T) ?
"nocona" :
"prescott";
438 return (Em64T) ?
"x86-64" :
"pentium4";
445 }
else if (memcmp(text.c,
"AuthenticAMD", 12) == 0) {
456 case 8:
return "k6-2";
458 case 13:
return "k6-3";
459 case 10:
return "geode";
460 default:
return "pentium";
464 case 4:
return "athlon-tbird";
467 case 8:
return "athlon-mp";
468 case 10:
return "athlon-xp";
469 default:
return "athlon";
475 case 1:
return "opteron";
476 case 5:
return "athlon-fx";
477 default:
return "athlon64";
490 if (Model >= 0x10 || HasTBM)
503 #elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
505 host_basic_info_data_t hostInfo;
506 mach_msg_type_number_t infoCount;
508 infoCount = HOST_BASIC_INFO_COUNT;
509 host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
514 switch(hostInfo.cpu_subtype) {
532 #elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
537 const char *
generic =
"generic";
542 ssize_t CPUInfoSize = readCpuInfo(buffer,
sizeof(buffer));
543 if (CPUInfoSize == -1)
546 const char *CPUInfoStart = buffer;
547 const char *CPUInfoEnd = buffer + CPUInfoSize;
549 const char *CIP = CPUInfoStart;
551 const char *CPUStart = 0;
556 while (CIP < CPUInfoEnd && CPUStart == 0) {
557 if (CIP < CPUInfoEnd && *CIP ==
'\n')
560 if (CIP < CPUInfoEnd && *CIP ==
'c') {
562 if (CIP < CPUInfoEnd && *CIP ==
'p') {
564 if (CIP < CPUInfoEnd && *CIP ==
'u') {
566 while (CIP < CPUInfoEnd && (*CIP ==
' ' || *CIP ==
'\t'))
569 if (CIP < CPUInfoEnd && *CIP ==
':') {
571 while (CIP < CPUInfoEnd && (*CIP ==
' ' || *CIP ==
'\t'))
574 if (CIP < CPUInfoEnd) {
576 while (CIP < CPUInfoEnd && (*CIP !=
' ' && *CIP !=
'\t' &&
577 *CIP !=
',' && *CIP !=
'\n'))
579 CPULen = CIP - CPUStart;
587 while (CIP < CPUInfoEnd && *CIP !=
'\n')
595 .Case(
"604e",
"604e")
597 .
Case(
"7400",
"7400")
598 .
Case(
"7410",
"7400")
599 .
Case(
"7447",
"7400")
600 .
Case(
"7455",
"7450")
602 .
Case(
"POWER4",
"970")
603 .
Case(
"PPC970FX",
"970")
604 .
Case(
"PPC970MP",
"970")
606 .
Case(
"POWER5",
"g5")
608 .
Case(
"POWER6",
"pwr6")
609 .
Case(
"POWER7",
"pwr7")
610 .
Case(
"POWER8",
"pwr8")
611 .
Case(
"POWER8E",
"pwr8")
614 #elif defined(__linux__) && defined(__arm__)
622 ssize_t CPUInfoSize = readCpuInfo(buffer,
sizeof(buffer));
623 if (CPUInfoSize == -1)
629 Str.split(Lines,
"\n");
633 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I)
634 if (Lines[
I].startswith(
"CPU implementer"))
635 Implementer = Lines[
I].substr(15).ltrim(
"\t :");
637 if (Implementer ==
"0x41")
639 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I)
640 if (Lines[
I].startswith(
"CPU part"))
645 .Case(
"0x926",
"arm926ej-s")
646 .
Case(
"0xb02",
"mpcore")
647 .
Case(
"0xb36",
"arm1136j-s")
648 .
Case(
"0xb56",
"arm1156t2-s")
649 .
Case(
"0xb76",
"arm1176jz-s")
650 .
Case(
"0xc08",
"cortex-a8")
651 .
Case(
"0xc09",
"cortex-a9")
652 .
Case(
"0xc0f",
"cortex-a15")
653 .
Case(
"0xc20",
"cortex-m0")
654 .
Case(
"0xc23",
"cortex-m3")
655 .
Case(
"0xc24",
"cortex-m4")
658 if (Implementer ==
"0x51")
660 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I)
661 if (Lines[
I].startswith(
"CPU part"))
666 .Case(
"0x06f",
"krait")
671 #elif defined(__linux__) && defined(__s390x__)
678 ssize_t CPUInfoSize = readCpuInfo(buffer,
sizeof(buffer));
679 if (CPUInfoSize == -1)
684 Str.split(Lines,
"\n");
688 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I)
689 if (Lines[
I].startswith(
"features")) {
690 size_t Pos = Lines[
I].find(
":");
692 Lines[
I].drop_front(Pos + 1).split(CPUFeatures,
" ");
700 bool HaveVectorSupport =
false;
701 for (
unsigned I = 0, E = CPUFeatures.
size();
I != E; ++
I) {
702 if (CPUFeatures[
I] ==
"vx")
703 HaveVectorSupport =
true;
707 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I) {
708 if (Lines[
I].startswith(
"processor ")) {
709 size_t Pos = Lines[
I].find(
"machine = ");
711 Pos +=
sizeof(
"machine = ") - 1;
713 if (!Lines[
I].drop_front(Pos).getAsInteger(10, Id)) {
714 if (Id >= 2964 && HaveVectorSupport)
734 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
735 || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
737 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
744 if (GetX86CpuIDAndInfo(0, &MaxLevel, text.u+0, text.u+2, text.u+1) ||
748 GetX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
750 Features[
"cmov"] = (EDX >> 15) & 1;
751 Features[
"mmx"] = (EDX >> 23) & 1;
752 Features[
"sse"] = (EDX >> 25) & 1;
753 Features[
"sse2"] = (EDX >> 26) & 1;
754 Features[
"sse3"] = (ECX >> 0) & 1;
755 Features[
"ssse3"] = (ECX >> 9) & 1;
756 Features[
"sse4.1"] = (ECX >> 19) & 1;
757 Features[
"sse4.2"] = (ECX >> 20) & 1;
759 Features[
"pclmul"] = (ECX >> 1) & 1;
760 Features[
"cx16"] = (ECX >> 13) & 1;
761 Features[
"movbe"] = (ECX >> 22) & 1;
762 Features[
"popcnt"] = (ECX >> 23) & 1;
763 Features[
"aes"] = (ECX >> 25) & 1;
764 Features[
"rdrnd"] = (ECX >> 30) & 1;
769 bool HasAVX = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
770 !GetX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
771 Features[
"avx"] = HasAVX;
772 Features[
"fma"] = HasAVX && (ECX >> 12) & 1;
773 Features[
"f16c"] = HasAVX && (ECX >> 29) & 1;
776 bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
778 unsigned MaxExtLevel;
779 GetX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
781 bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
782 !GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
783 Features[
"lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
784 Features[
"sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
785 Features[
"prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
786 Features[
"xop"] = HasAVX && HasExtLeaf1 && ((ECX >> 11) & 1);
787 Features[
"fma4"] = HasAVX && HasExtLeaf1 && ((ECX >> 16) & 1);
788 Features[
"tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
790 bool HasLeaf7 = MaxLevel >= 7 &&
791 !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
794 Features[
"avx2"] = HasAVX && HasLeaf7 && (EBX >> 5) & 1;
796 Features[
"fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
797 Features[
"bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
798 Features[
"hle"] = HasLeaf7 && ((EBX >> 4) & 1);
799 Features[
"bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
800 Features[
"rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
801 Features[
"rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
802 Features[
"adx"] = HasLeaf7 && ((EBX >> 19) & 1);
803 Features[
"sha"] = HasLeaf7 && ((EBX >> 29) & 1);
806 Features[
"avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
807 Features[
"avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
808 Features[
"avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
809 Features[
"avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
810 Features[
"avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
811 Features[
"avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
812 Features[
"avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
816 #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
821 ssize_t CPUInfoSize = readCpuInfo(buffer,
sizeof(buffer));
822 if (CPUInfoSize == -1)
828 Str.split(Lines,
"\n");
833 for (
unsigned I = 0, E = Lines.
size();
I != E; ++
I)
834 if (Lines[
I].startswith(
"Features")) {
835 Lines[
I].split(CPUFeatures,
" ");
839 #if defined(__aarch64__)
850 for (
unsigned I = 0, E = CPUFeatures.
size();
I != E; ++
I) {
852 #
if defined(__aarch64__)
853 .
Case(
"asimd",
"neon")
854 .
Case(
"fp",
"fp-armv8")
855 .
Case(
"crc32",
"crc")
857 .
Case(
"half",
"fp16")
858 .
Case(
"neon",
"neon")
859 .
Case(
"vfpv3",
"vfp3")
860 .
Case(
"vfpv3d16",
"d16")
861 .
Case(
"vfpv4",
"vfp4")
862 .
Case(
"idiva",
"hwdiv-arm")
863 .
Case(
"idivt",
"hwdiv")
867 #if defined(__aarch64__)
870 if (CPUFeatures[
I] ==
"aes")
872 else if (CPUFeatures[
I] ==
"pmull")
874 else if (CPUFeatures[
I] ==
"sha1")
876 else if (CPUFeatures[
I] ==
"sha2")
880 if (LLVMFeatureStr !=
"")
881 Features[LLVMFeatureStr] =
true;
884 #if defined(__aarch64__)
886 if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
887 Features[
"crypto"] =
true;
value_type read(const void *memory)
Read a value of a particular endianness from memory.
const FeatureBitset Features
const std::string & str() const
StringSwitch & Case(const char(&S)[N], const T &Value)
bool isArch64Bit() const
Test whether the architecture is 64-bit.
llvm::Triple get32BitArchVariant() const
Form a triple with a 32-bit variant of the current architecture.
A switch()-like statement whose cases are string literals.
#define LLVM_ATTRIBUTE_UNUSED
std::string normalize() const
Return the normalized form of this triple's string.
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Triple - Helper class for working with autoconf configuration names.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
R Default(const T &Value) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
llvm::Triple get64BitArchVariant() const
Form a triple with a 64-bit variant of the current architecture.
StringRef getHostCPUName()
getHostCPUName - Get the LLVM name for the host CPU.
std::error_code openFileForRead(const Twine &Name, int &ResultFD)
StringRef - Represent a constant reference to a string, i.e.
bool getHostCPUFeatures(StringMap< bool > &Features)
getHostCPUFeatures - Get the LLVM names for the host CPU features.
bool isArch32Bit() const
Test whether the architecture is 32-bit.