1218885Sdim//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// 2218885Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218885Sdim// 7218885Sdim//===----------------------------------------------------------------------===// 8218885Sdim// 9276479Sdim// This file implements the operating system Host concept. 10218885Sdim// 11218885Sdim//===----------------------------------------------------------------------===// 12218885Sdim 13249423Sdim#include "llvm/Support/Host.h" 14327952Sdim#include "llvm/Support/TargetParser.h" 15314564Sdim#include "llvm/ADT/SmallSet.h" 16239462Sdim#include "llvm/ADT/SmallVector.h" 17239462Sdim#include "llvm/ADT/StringRef.h" 18239462Sdim#include "llvm/ADT/StringSwitch.h" 19249423Sdim#include "llvm/ADT/Triple.h" 20341825Sdim#include "llvm/Config/llvm-config.h" 21239462Sdim#include "llvm/Support/Debug.h" 22280031Sdim#include "llvm/Support/FileSystem.h" 23314564Sdim#include "llvm/Support/MemoryBuffer.h" 24239462Sdim#include "llvm/Support/raw_ostream.h" 25314564Sdim#include <assert.h> 26218885Sdim#include <string.h> 27218885Sdim 28218885Sdim// Include the platform-specific parts of this class. 29218885Sdim#ifdef LLVM_ON_UNIX 30218885Sdim#include "Unix/Host.inc" 31218885Sdim#endif 32341825Sdim#ifdef _WIN32 33218885Sdim#include "Windows/Host.inc" 34218885Sdim#endif 35218885Sdim#ifdef _MSC_VER 36218885Sdim#include <intrin.h> 37218885Sdim#endif 38360784Sdim#if defined(__APPLE__) && (!defined(__x86_64__)) 39309124Sdim#include <mach/host_info.h> 40239462Sdim#include <mach/mach.h> 41239462Sdim#include <mach/mach_host.h> 42239462Sdim#include <mach/machine.h> 43239462Sdim#endif 44218885Sdim 45276479Sdim#define DEBUG_TYPE "host-detection" 46276479Sdim 47218885Sdim//===----------------------------------------------------------------------===// 48218885Sdim// 49218885Sdim// Implementations of the CPU detection routines 50218885Sdim// 51218885Sdim//===----------------------------------------------------------------------===// 52218885Sdim 53218885Sdimusing namespace llvm; 54218885Sdim 55321369Sdimstatic std::unique_ptr<llvm::MemoryBuffer> 56321369Sdim LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() { 57321369Sdim llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 58321369Sdim llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); 59321369Sdim if (std::error_code EC = Text.getError()) { 60321369Sdim llvm::errs() << "Can't read " 61321369Sdim << "/proc/cpuinfo: " << EC.message() << "\n"; 62321369Sdim return nullptr; 63321369Sdim } 64321369Sdim return std::move(*Text); 65321369Sdim} 66280031Sdim 67341825SdimStringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) { 68321369Sdim // Access to the Processor Version Register (PVR) on PowerPC is privileged, 69321369Sdim // and so we must use an operating-system interface to determine the current 70321369Sdim // processor type. On Linux, this is exposed through the /proc/cpuinfo file. 71321369Sdim const char *generic = "generic"; 72321369Sdim 73321369Sdim // The cpu line is second (after the 'processor: 0' line), so if this 74321369Sdim // buffer is too small then something has changed (or is wrong). 75321369Sdim StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin(); 76321369Sdim StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end(); 77321369Sdim 78321369Sdim StringRef::const_iterator CIP = CPUInfoStart; 79321369Sdim 80321369Sdim StringRef::const_iterator CPUStart = 0; 81321369Sdim size_t CPULen = 0; 82321369Sdim 83321369Sdim // We need to find the first line which starts with cpu, spaces, and a colon. 84321369Sdim // After the colon, there may be some additional spaces and then the cpu type. 85321369Sdim while (CIP < CPUInfoEnd && CPUStart == 0) { 86321369Sdim if (CIP < CPUInfoEnd && *CIP == '\n') 87321369Sdim ++CIP; 88321369Sdim 89321369Sdim if (CIP < CPUInfoEnd && *CIP == 'c') { 90321369Sdim ++CIP; 91321369Sdim if (CIP < CPUInfoEnd && *CIP == 'p') { 92321369Sdim ++CIP; 93321369Sdim if (CIP < CPUInfoEnd && *CIP == 'u') { 94321369Sdim ++CIP; 95321369Sdim while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 96321369Sdim ++CIP; 97321369Sdim 98321369Sdim if (CIP < CPUInfoEnd && *CIP == ':') { 99321369Sdim ++CIP; 100321369Sdim while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 101321369Sdim ++CIP; 102321369Sdim 103321369Sdim if (CIP < CPUInfoEnd) { 104321369Sdim CPUStart = CIP; 105321369Sdim while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && 106321369Sdim *CIP != ',' && *CIP != '\n')) 107321369Sdim ++CIP; 108321369Sdim CPULen = CIP - CPUStart; 109321369Sdim } 110321369Sdim } 111321369Sdim } 112321369Sdim } 113321369Sdim } 114321369Sdim 115321369Sdim if (CPUStart == 0) 116321369Sdim while (CIP < CPUInfoEnd && *CIP != '\n') 117321369Sdim ++CIP; 118280031Sdim } 119321369Sdim 120321369Sdim if (CPUStart == 0) 121321369Sdim return generic; 122321369Sdim 123321369Sdim return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) 124321369Sdim .Case("604e", "604e") 125321369Sdim .Case("604", "604") 126321369Sdim .Case("7400", "7400") 127321369Sdim .Case("7410", "7400") 128321369Sdim .Case("7447", "7400") 129321369Sdim .Case("7455", "7450") 130321369Sdim .Case("G4", "g4") 131321369Sdim .Case("POWER4", "970") 132321369Sdim .Case("PPC970FX", "970") 133321369Sdim .Case("PPC970MP", "970") 134321369Sdim .Case("G5", "g5") 135321369Sdim .Case("POWER5", "g5") 136321369Sdim .Case("A2", "a2") 137321369Sdim .Case("POWER6", "pwr6") 138321369Sdim .Case("POWER7", "pwr7") 139321369Sdim .Case("POWER8", "pwr8") 140321369Sdim .Case("POWER8E", "pwr8") 141321369Sdim .Case("POWER8NVL", "pwr8") 142321369Sdim .Case("POWER9", "pwr9") 143360784Sdim // FIXME: If we get a simulator or machine with the capabilities of 144360784Sdim // mcpu=future, we should revisit this and add the name reported by the 145360784Sdim // simulator/machine. 146321369Sdim .Default(generic); 147280031Sdim} 148280031Sdim 149341825SdimStringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { 150321369Sdim // The cpuid register on arm is not accessible from user space. On Linux, 151321369Sdim // it is exposed through the /proc/cpuinfo file. 152321369Sdim 153321369Sdim // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line 154321369Sdim // in all cases. 155321369Sdim SmallVector<StringRef, 32> Lines; 156321369Sdim ProcCpuinfoContent.split(Lines, "\n"); 157321369Sdim 158321369Sdim // Look for the CPU implementer line. 159321369Sdim StringRef Implementer; 160321369Sdim StringRef Hardware; 161321369Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 162321369Sdim if (Lines[I].startswith("CPU implementer")) 163321369Sdim Implementer = Lines[I].substr(15).ltrim("\t :"); 164321369Sdim if (Lines[I].startswith("Hardware")) 165321369Sdim Hardware = Lines[I].substr(8).ltrim("\t :"); 166321369Sdim } 167321369Sdim 168321369Sdim if (Implementer == "0x41") { // ARM Ltd. 169321369Sdim // MSM8992/8994 may give cpu part for the core that the kernel is running on, 170321369Sdim // which is undeterministic and wrong. Always return cortex-a53 for these SoC. 171321369Sdim if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996")) 172321369Sdim return "cortex-a53"; 173321369Sdim 174321369Sdim 175321369Sdim // Look for the CPU part line. 176321369Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 177321369Sdim if (Lines[I].startswith("CPU part")) 178321369Sdim // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 179321369Sdim // values correspond to the "Part number" in the CP15/c0 register. The 180321369Sdim // contents are specified in the various processor manuals. 181321369Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 182321369Sdim .Case("0x926", "arm926ej-s") 183321369Sdim .Case("0xb02", "mpcore") 184321369Sdim .Case("0xb36", "arm1136j-s") 185321369Sdim .Case("0xb56", "arm1156t2-s") 186321369Sdim .Case("0xb76", "arm1176jz-s") 187321369Sdim .Case("0xc08", "cortex-a8") 188321369Sdim .Case("0xc09", "cortex-a9") 189321369Sdim .Case("0xc0f", "cortex-a15") 190321369Sdim .Case("0xc20", "cortex-m0") 191321369Sdim .Case("0xc23", "cortex-m3") 192321369Sdim .Case("0xc24", "cortex-m4") 193321369Sdim .Case("0xd04", "cortex-a35") 194321369Sdim .Case("0xd03", "cortex-a53") 195321369Sdim .Case("0xd07", "cortex-a57") 196321369Sdim .Case("0xd08", "cortex-a72") 197321369Sdim .Case("0xd09", "cortex-a73") 198353358Sdim .Case("0xd0a", "cortex-a75") 199353358Sdim .Case("0xd0b", "cortex-a76") 200321369Sdim .Default("generic"); 201321369Sdim } 202321369Sdim 203344779Sdim if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium. 204344779Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 205344779Sdim if (Lines[I].startswith("CPU part")) { 206344779Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 207344779Sdim .Case("0x516", "thunderx2t99") 208344779Sdim .Case("0x0516", "thunderx2t99") 209344779Sdim .Case("0xaf", "thunderx2t99") 210344779Sdim .Case("0x0af", "thunderx2t99") 211344779Sdim .Case("0xa1", "thunderxt88") 212344779Sdim .Case("0x0a1", "thunderxt88") 213344779Sdim .Default("generic"); 214344779Sdim } 215344779Sdim } 216344779Sdim } 217344779Sdim 218344779Sdim if (Implementer == "0x48") // HiSilicon Technologies, Inc. 219344779Sdim // Look for the CPU part line. 220344779Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 221344779Sdim if (Lines[I].startswith("CPU part")) 222344779Sdim // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 223344779Sdim // values correspond to the "Part number" in the CP15/c0 register. The 224344779Sdim // contents are specified in the various processor manuals. 225344779Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 226344779Sdim .Case("0xd01", "tsv110") 227344779Sdim .Default("generic"); 228344779Sdim 229321369Sdim if (Implementer == "0x51") // Qualcomm Technologies, Inc. 230321369Sdim // Look for the CPU part line. 231321369Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 232321369Sdim if (Lines[I].startswith("CPU part")) 233321369Sdim // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 234321369Sdim // values correspond to the "Part number" in the CP15/c0 register. The 235321369Sdim // contents are specified in the various processor manuals. 236321369Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 237321369Sdim .Case("0x06f", "krait") // APQ8064 238321369Sdim .Case("0x201", "kryo") 239321369Sdim .Case("0x205", "kryo") 240327952Sdim .Case("0x211", "kryo") 241327952Sdim .Case("0x800", "cortex-a73") 242327952Sdim .Case("0x801", "cortex-a73") 243353358Sdim .Case("0x802", "cortex-a73") 244353358Sdim .Case("0x803", "cortex-a73") 245353358Sdim .Case("0x804", "cortex-a73") 246353358Sdim .Case("0x805", "cortex-a73") 247326496Sdim .Case("0xc00", "falkor") 248327952Sdim .Case("0xc01", "saphira") 249321369Sdim .Default("generic"); 250321369Sdim 251327952Sdim if (Implementer == "0x53") { // Samsung Electronics Co., Ltd. 252327952Sdim // The Exynos chips have a convoluted ID scheme that doesn't seem to follow 253327952Sdim // any predictive pattern across variants and parts. 254327952Sdim unsigned Variant = 0, Part = 0; 255327952Sdim 256327952Sdim // Look for the CPU variant line, whose value is a 1 digit hexadecimal 257327952Sdim // number, corresponding to the Variant bits in the CP15/C0 register. 258327952Sdim for (auto I : Lines) 259327952Sdim if (I.consume_front("CPU variant")) 260327952Sdim I.ltrim("\t :").getAsInteger(0, Variant); 261327952Sdim 262327952Sdim // Look for the CPU part line, whose value is a 3 digit hexadecimal 263327952Sdim // number, corresponding to the PartNum bits in the CP15/C0 register. 264327952Sdim for (auto I : Lines) 265327952Sdim if (I.consume_front("CPU part")) 266327952Sdim I.ltrim("\t :").getAsInteger(0, Part); 267327952Sdim 268327952Sdim unsigned Exynos = (Variant << 12) | Part; 269327952Sdim switch (Exynos) { 270327952Sdim default: 271360784Sdim // Default by falling through to Exynos M3. 272327952Sdim LLVM_FALLTHROUGH; 273360784Sdim case 0x1002: 274360784Sdim return "exynos-m3"; 275360784Sdim case 0x1003: 276360784Sdim return "exynos-m4"; 277327952Sdim } 278327952Sdim } 279327952Sdim 280321369Sdim return "generic"; 281321369Sdim} 282321369Sdim 283341825SdimStringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) { 284321369Sdim // STIDP is a privileged operation, so use /proc/cpuinfo instead. 285321369Sdim 286321369Sdim // The "processor 0:" line comes after a fair amount of other information, 287321369Sdim // including a cache breakdown, but this should be plenty. 288321369Sdim SmallVector<StringRef, 32> Lines; 289321369Sdim ProcCpuinfoContent.split(Lines, "\n"); 290321369Sdim 291321369Sdim // Look for the CPU features. 292321369Sdim SmallVector<StringRef, 32> CPUFeatures; 293321369Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 294321369Sdim if (Lines[I].startswith("features")) { 295321369Sdim size_t Pos = Lines[I].find(":"); 296321369Sdim if (Pos != StringRef::npos) { 297321369Sdim Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); 298321369Sdim break; 299321369Sdim } 300321369Sdim } 301321369Sdim 302321369Sdim // We need to check for the presence of vector support independently of 303321369Sdim // the machine type, since we may only use the vector register set when 304321369Sdim // supported by the kernel (and hypervisor). 305321369Sdim bool HaveVectorSupport = false; 306321369Sdim for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 307321369Sdim if (CPUFeatures[I] == "vx") 308321369Sdim HaveVectorSupport = true; 309321369Sdim } 310321369Sdim 311321369Sdim // Now check the processor machine type. 312321369Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 313321369Sdim if (Lines[I].startswith("processor ")) { 314321369Sdim size_t Pos = Lines[I].find("machine = "); 315321369Sdim if (Pos != StringRef::npos) { 316321369Sdim Pos += sizeof("machine = ") - 1; 317321369Sdim unsigned int Id; 318321369Sdim if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) { 319353358Sdim if (Id >= 8561 && HaveVectorSupport) 320360784Sdim return "z15"; 321321369Sdim if (Id >= 3906 && HaveVectorSupport) 322321369Sdim return "z14"; 323321369Sdim if (Id >= 2964 && HaveVectorSupport) 324321369Sdim return "z13"; 325321369Sdim if (Id >= 2827) 326321369Sdim return "zEC12"; 327321369Sdim if (Id >= 2817) 328321369Sdim return "z196"; 329321369Sdim } 330321369Sdim } 331321369Sdim break; 332321369Sdim } 333321369Sdim } 334321369Sdim 335321369Sdim return "generic"; 336321369Sdim} 337321369Sdim 338327952SdimStringRef sys::detail::getHostCPUNameForBPF() { 339327952Sdim#if !defined(__linux__) || !defined(__x86_64__) 340327952Sdim return "generic"; 341327952Sdim#else 342353358Sdim uint8_t v3_insns[40] __attribute__ ((aligned (8))) = 343327952Sdim /* BPF_MOV64_IMM(BPF_REG_0, 0) */ 344327952Sdim { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 345327952Sdim /* BPF_MOV64_IMM(BPF_REG_2, 1) */ 346327952Sdim 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 347353358Sdim /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */ 348353358Sdim 0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 349353358Sdim /* BPF_MOV64_IMM(BPF_REG_0, 1) */ 350353358Sdim 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 351353358Sdim /* BPF_EXIT_INSN() */ 352353358Sdim 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 353353358Sdim 354353358Sdim uint8_t v2_insns[40] __attribute__ ((aligned (8))) = 355353358Sdim /* BPF_MOV64_IMM(BPF_REG_0, 0) */ 356353358Sdim { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 357353358Sdim /* BPF_MOV64_IMM(BPF_REG_2, 1) */ 358353358Sdim 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 359327952Sdim /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */ 360327952Sdim 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 361327952Sdim /* BPF_MOV64_IMM(BPF_REG_0, 1) */ 362327952Sdim 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 363327952Sdim /* BPF_EXIT_INSN() */ 364327952Sdim 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 365327952Sdim 366327952Sdim struct bpf_prog_load_attr { 367327952Sdim uint32_t prog_type; 368327952Sdim uint32_t insn_cnt; 369327952Sdim uint64_t insns; 370327952Sdim uint64_t license; 371327952Sdim uint32_t log_level; 372327952Sdim uint32_t log_size; 373327952Sdim uint64_t log_buf; 374327952Sdim uint32_t kern_version; 375327952Sdim uint32_t prog_flags; 376327952Sdim } attr = {}; 377327952Sdim attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */ 378327952Sdim attr.insn_cnt = 5; 379353358Sdim attr.insns = (uint64_t)v3_insns; 380327952Sdim attr.license = (uint64_t)"DUMMY"; 381327952Sdim 382353358Sdim int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, 383353358Sdim sizeof(attr)); 384327952Sdim if (fd >= 0) { 385327952Sdim close(fd); 386353358Sdim return "v3"; 387353358Sdim } 388353358Sdim 389353358Sdim /* Clear the whole attr in case its content changed by syscall. */ 390353358Sdim memset(&attr, 0, sizeof(attr)); 391353358Sdim attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */ 392353358Sdim attr.insn_cnt = 5; 393353358Sdim attr.insns = (uint64_t)v2_insns; 394353358Sdim attr.license = (uint64_t)"DUMMY"; 395353358Sdim fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr)); 396353358Sdim if (fd >= 0) { 397353358Sdim close(fd); 398327952Sdim return "v2"; 399327952Sdim } 400327952Sdim return "v1"; 401327952Sdim#endif 402327952Sdim} 403327952Sdim 404314564Sdim#if defined(__i386__) || defined(_M_IX86) || \ 405314564Sdim defined(__x86_64__) || defined(_M_X64) 406218885Sdim 407309124Sdimenum VendorSignatures { 408309124Sdim SIG_INTEL = 0x756e6547 /* Genu */, 409309124Sdim SIG_AMD = 0x68747541 /* Auth */ 410309124Sdim}; 411309124Sdim 412314564Sdim// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). 413314564Sdim// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID 414314564Sdim// support. Consequently, for i386, the presence of CPUID is checked first 415314564Sdim// via the corresponding eflags bit. 416314564Sdim// Removal of cpuid.h header motivated by PR30384 417314564Sdim// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp 418314564Sdim// or test-suite, but are used in external projects e.g. libstdcxx 419314564Sdimstatic bool isCpuIdSupported() { 420314564Sdim#if defined(__GNUC__) || defined(__clang__) 421314564Sdim#if defined(__i386__) 422314564Sdim int __cpuid_supported; 423314564Sdim __asm__(" pushfl\n" 424314564Sdim " popl %%eax\n" 425314564Sdim " movl %%eax,%%ecx\n" 426314564Sdim " xorl $0x00200000,%%eax\n" 427314564Sdim " pushl %%eax\n" 428314564Sdim " popfl\n" 429314564Sdim " pushfl\n" 430314564Sdim " popl %%eax\n" 431314564Sdim " movl $0,%0\n" 432314564Sdim " cmpl %%eax,%%ecx\n" 433314564Sdim " je 1f\n" 434314564Sdim " movl $1,%0\n" 435314564Sdim "1:" 436314564Sdim : "=r"(__cpuid_supported) 437314564Sdim : 438314564Sdim : "eax", "ecx"); 439314564Sdim if (!__cpuid_supported) 440314564Sdim return false; 441314564Sdim#endif 442314564Sdim return true; 443314564Sdim#endif 444314564Sdim return true; 445314564Sdim} 446314564Sdim 447309124Sdim/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in 448309124Sdim/// the specified arguments. If we can't run cpuid on the host, return true. 449309124Sdimstatic bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, 450261991Sdim unsigned *rECX, unsigned *rEDX) { 451261991Sdim#if defined(__GNUC__) || defined(__clang__) 452314564Sdim#if defined(__x86_64__) 453314564Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. 454314564Sdim // FIXME: should we save this for Clang? 455314564Sdim __asm__("movq\t%%rbx, %%rsi\n\t" 456314564Sdim "cpuid\n\t" 457314564Sdim "xchgq\t%%rbx, %%rsi\n\t" 458314564Sdim : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 459314564Sdim : "a"(value)); 460321369Sdim return false; 461314564Sdim#elif defined(__i386__) 462314564Sdim __asm__("movl\t%%ebx, %%esi\n\t" 463314564Sdim "cpuid\n\t" 464314564Sdim "xchgl\t%%ebx, %%esi\n\t" 465314564Sdim : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 466314564Sdim : "a"(value)); 467321369Sdim return false; 468309124Sdim#else 469321369Sdim return true; 470309124Sdim#endif 471261991Sdim#elif defined(_MSC_VER) 472261991Sdim // The MSVC intrinsic is portable across x86 and x64. 473261991Sdim int registers[4]; 474261991Sdim __cpuid(registers, value); 475261991Sdim *rEAX = registers[0]; 476261991Sdim *rEBX = registers[1]; 477261991Sdim *rECX = registers[2]; 478261991Sdim *rEDX = registers[3]; 479261991Sdim return false; 480261991Sdim#else 481261991Sdim return true; 482261991Sdim#endif 483261991Sdim} 484261991Sdim 485309124Sdim/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return 486309124Sdim/// the 4 values in the specified arguments. If we can't run cpuid on the host, 487261991Sdim/// return true. 488309124Sdimstatic bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, 489276479Sdim unsigned *rEAX, unsigned *rEBX, unsigned *rECX, 490276479Sdim unsigned *rEDX) { 491314564Sdim#if defined(__GNUC__) || defined(__clang__) 492321369Sdim#if defined(__x86_64__) 493321369Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. 494314564Sdim // FIXME: should we save this for Clang? 495314564Sdim __asm__("movq\t%%rbx, %%rsi\n\t" 496314564Sdim "cpuid\n\t" 497314564Sdim "xchgq\t%%rbx, %%rsi\n\t" 498314564Sdim : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 499314564Sdim : "a"(value), "c"(subleaf)); 500321369Sdim return false; 501321369Sdim#elif defined(__i386__) 502321369Sdim __asm__("movl\t%%ebx, %%esi\n\t" 503321369Sdim "cpuid\n\t" 504321369Sdim "xchgl\t%%ebx, %%esi\n\t" 505321369Sdim : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 506321369Sdim : "a"(value), "c"(subleaf)); 507321369Sdim return false; 508321369Sdim#else 509321369Sdim return true; 510321369Sdim#endif 511309124Sdim#elif defined(_MSC_VER) 512309124Sdim int registers[4]; 513309124Sdim __cpuidex(registers, value, subleaf); 514309124Sdim *rEAX = registers[0]; 515309124Sdim *rEBX = registers[1]; 516309124Sdim *rECX = registers[2]; 517309124Sdim *rEDX = registers[3]; 518314564Sdim return false; 519309124Sdim#else 520309124Sdim return true; 521309124Sdim#endif 522218885Sdim} 523218885Sdim 524321369Sdim// Read control register 0 (XCR0). Used to detect features such as AVX. 525309124Sdimstatic bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { 526314564Sdim#if defined(__GNUC__) || defined(__clang__) 527251662Sdim // Check xgetbv; this uses a .byte sequence instead of the instruction 528251662Sdim // directly because older assemblers do not include support for xgetbv and 529251662Sdim // there is no easy way to conditionally compile based on the assembler used. 530309124Sdim __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); 531288943Sdim return false; 532251662Sdim#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) 533288943Sdim unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 534288943Sdim *rEAX = Result; 535288943Sdim *rEDX = Result >> 32; 536288943Sdim return false; 537251662Sdim#else 538288943Sdim return true; 539251662Sdim#endif 540249423Sdim} 541249423Sdim 542309124Sdimstatic void detectX86FamilyModel(unsigned EAX, unsigned *Family, 543309124Sdim unsigned *Model) { 544309124Sdim *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 545309124Sdim *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 546309124Sdim if (*Family == 6 || *Family == 0xf) { 547309124Sdim if (*Family == 0xf) 548218885Sdim // Examine extended family ID if family ID is F. 549309124Sdim *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 550218885Sdim // Examine extended model ID if family ID is 6 or F. 551309124Sdim *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 552218885Sdim } 553218885Sdim} 554218885Sdim 555309124Sdimstatic void 556321369SdimgetIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, 557321369Sdim unsigned Brand_id, unsigned Features, 558344779Sdim unsigned Features2, unsigned Features3, 559344779Sdim unsigned *Type, unsigned *Subtype) { 560309124Sdim if (Brand_id != 0) 561309124Sdim return; 562309124Sdim switch (Family) { 563309124Sdim case 3: 564327952Sdim *Type = X86::INTEL_i386; 565309124Sdim break; 566309124Sdim case 4: 567327952Sdim *Type = X86::INTEL_i486; 568309124Sdim break; 569309124Sdim case 5: 570327952Sdim if (Features & (1 << X86::FEATURE_MMX)) { 571327952Sdim *Type = X86::INTEL_PENTIUM_MMX; 572309124Sdim break; 573309124Sdim } 574327952Sdim *Type = X86::INTEL_PENTIUM; 575309124Sdim break; 576309124Sdim case 6: 577309124Sdim switch (Model) { 578309124Sdim case 0x01: // Pentium Pro processor 579327952Sdim *Type = X86::INTEL_PENTIUM_PRO; 580309124Sdim break; 581309124Sdim case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, 582218885Sdim // model 03 583309124Sdim case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, 584218885Sdim // model 05, and Intel Celeron processor, model 05 585309124Sdim case 0x06: // Celeron processor, model 06 586327952Sdim *Type = X86::INTEL_PENTIUM_II; 587309124Sdim break; 588309124Sdim case 0x07: // Pentium III processor, model 07, and Pentium III Xeon 589218885Sdim // processor, model 07 590309124Sdim case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, 591218885Sdim // model 08, and Celeron processor, model 08 592309124Sdim case 0x0a: // Pentium III Xeon processor, model 0Ah 593309124Sdim case 0x0b: // Pentium III processor, model 0Bh 594327952Sdim *Type = X86::INTEL_PENTIUM_III; 595309124Sdim break; 596309124Sdim case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. 597309124Sdim case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model 598218885Sdim // 0Dh. All processors are manufactured using the 90 nm process. 599309124Sdim case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 600288943Sdim // Integrated Processor with Intel QuickAssist Technology 601327952Sdim *Type = X86::INTEL_PENTIUM_M; 602309124Sdim break; 603309124Sdim case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model 604218885Sdim // 0Eh. All processors are manufactured using the 65 nm process. 605327952Sdim *Type = X86::INTEL_CORE_DUO; 606309124Sdim break; // yonah 607309124Sdim case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 608218885Sdim // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 609218885Sdim // mobile processor, Intel Core 2 Extreme processor, Intel 610218885Sdim // Pentium Dual-Core processor, Intel Xeon processor, model 611218885Sdim // 0Fh. All processors are manufactured using the 65 nm process. 612309124Sdim case 0x16: // Intel Celeron processor model 16h. All processors are 613218885Sdim // manufactured using the 65 nm process 614327952Sdim *Type = X86::INTEL_CORE2; // "core2" 615327952Sdim *Subtype = X86::INTEL_CORE2_65; 616309124Sdim break; 617309124Sdim case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model 618218885Sdim // 17h. All processors are manufactured using the 45 nm process. 619218885Sdim // 620218885Sdim // 45nm: Penryn , Wolfdale, Yorkfield (XE) 621309124Sdim case 0x1d: // Intel Xeon processor MP. All processors are manufactured using 622288943Sdim // the 45 nm process. 623327952Sdim *Type = X86::INTEL_CORE2; // "penryn" 624327952Sdim *Subtype = X86::INTEL_CORE2_45; 625309124Sdim break; 626309124Sdim case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All 627218885Sdim // processors are manufactured using the 45 nm process. 628309124Sdim case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 629218885Sdim // As found in a Summer 2010 model iMac. 630309124Sdim case 0x1f: 631309124Sdim case 0x2e: // Nehalem EX 632327952Sdim *Type = X86::INTEL_COREI7; // "nehalem" 633327952Sdim *Subtype = X86::INTEL_COREI7_NEHALEM; 634309124Sdim break; 635309124Sdim case 0x25: // Intel Core i7, laptop version. 636309124Sdim case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All 637226633Sdim // processors are manufactured using the 32 nm process. 638309124Sdim case 0x2f: // Westmere EX 639327952Sdim *Type = X86::INTEL_COREI7; // "westmere" 640327952Sdim *Subtype = X86::INTEL_COREI7_WESTMERE; 641309124Sdim break; 642309124Sdim case 0x2a: // Intel Core i7 processor. All processors are manufactured 643224145Sdim // using the 32 nm process. 644309124Sdim case 0x2d: 645327952Sdim *Type = X86::INTEL_COREI7; //"sandybridge" 646327952Sdim *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; 647309124Sdim break; 648309124Sdim case 0x3a: 649309124Sdim case 0x3e: // Ivy Bridge EP 650327952Sdim *Type = X86::INTEL_COREI7; // "ivybridge" 651327952Sdim *Subtype = X86::INTEL_COREI7_IVYBRIDGE; 652309124Sdim break; 653218885Sdim 654309124Sdim // Haswell: 655309124Sdim case 0x3c: 656309124Sdim case 0x3f: 657309124Sdim case 0x45: 658309124Sdim case 0x46: 659327952Sdim *Type = X86::INTEL_COREI7; // "haswell" 660327952Sdim *Subtype = X86::INTEL_COREI7_HASWELL; 661309124Sdim break; 662239462Sdim 663309124Sdim // Broadwell: 664309124Sdim case 0x3d: 665309124Sdim case 0x47: 666309124Sdim case 0x4f: 667309124Sdim case 0x56: 668327952Sdim *Type = X86::INTEL_COREI7; // "broadwell" 669327952Sdim *Subtype = X86::INTEL_COREI7_BROADWELL; 670309124Sdim break; 671261991Sdim 672309124Sdim // Skylake: 673353358Sdim case 0x4e: // Skylake mobile 674353358Sdim case 0x5e: // Skylake desktop 675353358Sdim case 0x8e: // Kaby Lake mobile 676353358Sdim case 0x9e: // Kaby Lake desktop 677327952Sdim *Type = X86::INTEL_COREI7; // "skylake" 678327952Sdim *Subtype = X86::INTEL_COREI7_SKYLAKE; 679309124Sdim break; 680288943Sdim 681314564Sdim // Skylake Xeon: 682314564Sdim case 0x55: 683327952Sdim *Type = X86::INTEL_COREI7; 684360784Sdim if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32))) 685353358Sdim *Subtype = X86::INTEL_COREI7_COOPERLAKE; // "cooperlake" 686353358Sdim else if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32))) 687353358Sdim *Subtype = X86::INTEL_COREI7_CASCADELAKE; // "cascadelake" 688353358Sdim else 689353358Sdim *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512" 690314564Sdim break; 691314564Sdim 692327952Sdim // Cannonlake: 693327952Sdim case 0x66: 694327952Sdim *Type = X86::INTEL_COREI7; 695327952Sdim *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake" 696327952Sdim break; 697327952Sdim 698353358Sdim // Icelake: 699353358Sdim case 0x7d: 700353358Sdim case 0x7e: 701353358Sdim *Type = X86::INTEL_COREI7; 702353358Sdim *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; // "icelake-client" 703353358Sdim break; 704353358Sdim 705353358Sdim // Icelake Xeon: 706353358Sdim case 0x6a: 707353358Sdim case 0x6c: 708353358Sdim *Type = X86::INTEL_COREI7; 709353358Sdim *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER; // "icelake-server" 710353358Sdim break; 711353358Sdim 712309124Sdim case 0x1c: // Most 45 nm Intel Atom processors 713309124Sdim case 0x26: // 45 nm Atom Lincroft 714309124Sdim case 0x27: // 32 nm Atom Medfield 715309124Sdim case 0x35: // 32 nm Atom Midview 716309124Sdim case 0x36: // 32 nm Atom Midview 717327952Sdim *Type = X86::INTEL_BONNELL; 718309124Sdim break; // "bonnell" 719296417Sdim 720309124Sdim // Atom Silvermont codes from the Intel software optimization guide. 721309124Sdim case 0x37: 722309124Sdim case 0x4a: 723309124Sdim case 0x4d: 724309124Sdim case 0x5a: 725309124Sdim case 0x5d: 726309124Sdim case 0x4c: // really airmont 727327952Sdim *Type = X86::INTEL_SILVERMONT; 728309124Sdim break; // "silvermont" 729321369Sdim // Goldmont: 730327952Sdim case 0x5c: // Apollo Lake 731327952Sdim case 0x5f: // Denverton 732327952Sdim *Type = X86::INTEL_GOLDMONT; 733321369Sdim break; // "goldmont" 734341825Sdim case 0x7a: 735341825Sdim *Type = X86::INTEL_GOLDMONT_PLUS; 736341825Sdim break; 737353358Sdim case 0x86: 738353358Sdim *Type = X86::INTEL_TREMONT; 739353358Sdim break; 740353358Sdim 741309124Sdim case 0x57: 742327952Sdim *Type = X86::INTEL_KNL; // knl 743309124Sdim break; 744353358Sdim 745327952Sdim case 0x85: 746327952Sdim *Type = X86::INTEL_KNM; // knm 747327952Sdim break; 748261991Sdim 749309124Sdim default: // Unknown family 6 CPU, try to guess. 750360784Sdim // TODO detect tigerlake host 751360784Sdim if (Features3 & (1 << (X86::FEATURE_AVX512VP2INTERSECT - 64))) { 752360784Sdim *Type = X86::INTEL_COREI7; 753360784Sdim *Subtype = X86::INTEL_COREI7_TIGERLAKE; 754360784Sdim break; 755360784Sdim } 756360784Sdim 757344779Sdim if (Features & (1 << X86::FEATURE_AVX512VBMI2)) { 758344779Sdim *Type = X86::INTEL_COREI7; 759344779Sdim *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; 760344779Sdim break; 761344779Sdim } 762344779Sdim 763327952Sdim if (Features & (1 << X86::FEATURE_AVX512VBMI)) { 764327952Sdim *Type = X86::INTEL_COREI7; 765327952Sdim *Subtype = X86::INTEL_COREI7_CANNONLAKE; 766309124Sdim break; 767218885Sdim } 768327952Sdim 769360784Sdim if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32))) { 770353358Sdim *Type = X86::INTEL_COREI7; 771353358Sdim *Subtype = X86::INTEL_COREI7_COOPERLAKE; 772353358Sdim break; 773353358Sdim } 774353358Sdim 775344779Sdim if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32))) { 776344779Sdim *Type = X86::INTEL_COREI7; 777344779Sdim *Subtype = X86::INTEL_COREI7_CASCADELAKE; 778344779Sdim break; 779344779Sdim } 780344779Sdim 781327952Sdim if (Features & (1 << X86::FEATURE_AVX512VL)) { 782327952Sdim *Type = X86::INTEL_COREI7; 783327952Sdim *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; 784309124Sdim break; 785309124Sdim } 786327952Sdim 787327952Sdim if (Features & (1 << X86::FEATURE_AVX512ER)) { 788327952Sdim *Type = X86::INTEL_KNL; // knl 789309124Sdim break; 790309124Sdim } 791327952Sdim 792344779Sdim if (Features3 & (1 << (X86::FEATURE_CLFLUSHOPT - 64))) { 793344779Sdim if (Features3 & (1 << (X86::FEATURE_SHA - 64))) { 794327952Sdim *Type = X86::INTEL_GOLDMONT; 795327952Sdim } else { 796327952Sdim *Type = X86::INTEL_COREI7; 797327952Sdim *Subtype = X86::INTEL_COREI7_SKYLAKE; 798327952Sdim } 799309124Sdim break; 800309124Sdim } 801344779Sdim if (Features3 & (1 << (X86::FEATURE_ADX - 64))) { 802327952Sdim *Type = X86::INTEL_COREI7; 803327952Sdim *Subtype = X86::INTEL_COREI7_BROADWELL; 804327952Sdim break; 805327952Sdim } 806327952Sdim if (Features & (1 << X86::FEATURE_AVX2)) { 807327952Sdim *Type = X86::INTEL_COREI7; 808327952Sdim *Subtype = X86::INTEL_COREI7_HASWELL; 809327952Sdim break; 810327952Sdim } 811327952Sdim if (Features & (1 << X86::FEATURE_AVX)) { 812327952Sdim *Type = X86::INTEL_COREI7; 813327952Sdim *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; 814327952Sdim break; 815327952Sdim } 816327952Sdim if (Features & (1 << X86::FEATURE_SSE4_2)) { 817344779Sdim if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) { 818327952Sdim *Type = X86::INTEL_SILVERMONT; 819309124Sdim } else { 820327952Sdim *Type = X86::INTEL_COREI7; 821327952Sdim *Subtype = X86::INTEL_COREI7_NEHALEM; 822309124Sdim } 823309124Sdim break; 824309124Sdim } 825327952Sdim if (Features & (1 << X86::FEATURE_SSE4_1)) { 826327952Sdim *Type = X86::INTEL_CORE2; // "penryn" 827327952Sdim *Subtype = X86::INTEL_CORE2_45; 828309124Sdim break; 829309124Sdim } 830327952Sdim if (Features & (1 << X86::FEATURE_SSSE3)) { 831344779Sdim if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) { 832327952Sdim *Type = X86::INTEL_BONNELL; // "bonnell" 833309124Sdim } else { 834327952Sdim *Type = X86::INTEL_CORE2; // "core2" 835327952Sdim *Subtype = X86::INTEL_CORE2_65; 836309124Sdim } 837309124Sdim break; 838309124Sdim } 839344779Sdim if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) { 840327952Sdim *Type = X86::INTEL_CORE2; // "core2" 841327952Sdim *Subtype = X86::INTEL_CORE2_65; 842327952Sdim break; 843309124Sdim } 844327952Sdim if (Features & (1 << X86::FEATURE_SSE3)) { 845327952Sdim *Type = X86::INTEL_CORE_DUO; 846309124Sdim break; 847309124Sdim } 848327952Sdim if (Features & (1 << X86::FEATURE_SSE2)) { 849327952Sdim *Type = X86::INTEL_PENTIUM_M; 850309124Sdim break; 851309124Sdim } 852327952Sdim if (Features & (1 << X86::FEATURE_SSE)) { 853327952Sdim *Type = X86::INTEL_PENTIUM_III; 854309124Sdim break; 855309124Sdim } 856327952Sdim if (Features & (1 << X86::FEATURE_MMX)) { 857327952Sdim *Type = X86::INTEL_PENTIUM_II; 858327952Sdim break; 859327952Sdim } 860327952Sdim *Type = X86::INTEL_PENTIUM_PRO; 861309124Sdim break; 862309124Sdim } 863309124Sdim break; 864309124Sdim case 15: { 865344779Sdim if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) { 866327952Sdim *Type = X86::INTEL_NOCONA; 867309124Sdim break; 868327952Sdim } 869327952Sdim if (Features & (1 << X86::FEATURE_SSE3)) { 870327952Sdim *Type = X86::INTEL_PRESCOTT; 871309124Sdim break; 872218885Sdim } 873327952Sdim *Type = X86::INTEL_PENTIUM_IV; 874309124Sdim break; 875309124Sdim } 876309124Sdim default: 877309124Sdim break; /*"generic"*/ 878309124Sdim } 879309124Sdim} 880218885Sdim 881321369Sdimstatic void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, 882321369Sdim unsigned Features, unsigned *Type, 883309124Sdim unsigned *Subtype) { 884309124Sdim // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 885309124Sdim // appears to be no way to generate the wide variety of AMD-specific targets 886309124Sdim // from the information returned from CPUID. 887309124Sdim switch (Family) { 888309124Sdim case 4: 889327952Sdim *Type = X86::AMD_i486; 890309124Sdim break; 891309124Sdim case 5: 892327952Sdim *Type = X86::AMDPENTIUM; 893309124Sdim switch (Model) { 894309124Sdim case 6: 895309124Sdim case 7: 896327952Sdim *Subtype = X86::AMDPENTIUM_K6; 897309124Sdim break; // "k6" 898309124Sdim case 8: 899327952Sdim *Subtype = X86::AMDPENTIUM_K62; 900309124Sdim break; // "k6-2" 901309124Sdim case 9: 902309124Sdim case 13: 903327952Sdim *Subtype = X86::AMDPENTIUM_K63; 904309124Sdim break; // "k6-3" 905309124Sdim case 10: 906327952Sdim *Subtype = X86::AMDPENTIUM_GEODE; 907309124Sdim break; // "geode" 908309124Sdim } 909309124Sdim break; 910309124Sdim case 6: 911327952Sdim if (Features & (1 << X86::FEATURE_SSE)) { 912327952Sdim *Type = X86::AMD_ATHLON_XP; 913309124Sdim break; // "athlon-xp" 914309124Sdim } 915327952Sdim *Type = X86::AMD_ATHLON; 916321369Sdim break; // "athlon" 917309124Sdim case 15: 918327952Sdim if (Features & (1 << X86::FEATURE_SSE3)) { 919327952Sdim *Type = X86::AMD_K8SSE3; 920309124Sdim break; // "k8-sse3" 921309124Sdim } 922327952Sdim *Type = X86::AMD_K8; 923321369Sdim break; // "k8" 924309124Sdim case 16: 925327952Sdim *Type = X86::AMDFAM10H; // "amdfam10" 926309124Sdim switch (Model) { 927309124Sdim case 2: 928327952Sdim *Subtype = X86::AMDFAM10H_BARCELONA; 929309124Sdim break; 930309124Sdim case 4: 931327952Sdim *Subtype = X86::AMDFAM10H_SHANGHAI; 932309124Sdim break; 933309124Sdim case 8: 934327952Sdim *Subtype = X86::AMDFAM10H_ISTANBUL; 935309124Sdim break; 936309124Sdim } 937309124Sdim break; 938309124Sdim case 20: 939327952Sdim *Type = X86::AMD_BTVER1; 940309124Sdim break; // "btver1"; 941309124Sdim case 21: 942327952Sdim *Type = X86::AMDFAM15H; 943321369Sdim if (Model >= 0x60 && Model <= 0x7f) { 944327952Sdim *Subtype = X86::AMDFAM15H_BDVER4; 945321369Sdim break; // "bdver4"; 60h-7Fh: Excavator 946309124Sdim } 947309124Sdim if (Model >= 0x30 && Model <= 0x3f) { 948327952Sdim *Subtype = X86::AMDFAM15H_BDVER3; 949309124Sdim break; // "bdver3"; 30h-3Fh: Steamroller 950309124Sdim } 951341825Sdim if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) { 952327952Sdim *Subtype = X86::AMDFAM15H_BDVER2; 953341825Sdim break; // "bdver2"; 02h, 10h-1Fh: Piledriver 954309124Sdim } 955309124Sdim if (Model <= 0x0f) { 956327952Sdim *Subtype = X86::AMDFAM15H_BDVER1; 957309124Sdim break; // "bdver1"; 00h-0Fh: Bulldozer 958309124Sdim } 959309124Sdim break; 960309124Sdim case 22: 961327952Sdim *Type = X86::AMD_BTVER2; 962309124Sdim break; // "btver2" 963314564Sdim case 23: 964327952Sdim *Type = X86::AMDFAM17H; 965360784Sdim if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) { 966353358Sdim *Subtype = X86::AMDFAM17H_ZNVER2; 967360784Sdim break; // "znver2"; 30h-3fh, 71h: Zen2 968353358Sdim } 969353358Sdim if (Model <= 0x0f) { 970353358Sdim *Subtype = X86::AMDFAM17H_ZNVER1; 971353358Sdim break; // "znver1"; 00h-0Fh: Zen1 972353358Sdim } 973314564Sdim break; 974309124Sdim default: 975309124Sdim break; // "generic" 976309124Sdim } 977309124Sdim} 978309124Sdim 979321369Sdimstatic void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, 980344779Sdim unsigned *FeaturesOut, unsigned *Features2Out, 981344779Sdim unsigned *Features3Out) { 982309124Sdim unsigned Features = 0; 983321369Sdim unsigned Features2 = 0; 984344779Sdim unsigned Features3 = 0; 985321369Sdim unsigned EAX, EBX; 986309124Sdim 987344779Sdim auto setFeature = [&](unsigned F) { 988344779Sdim if (F < 32) 989344779Sdim Features |= 1U << (F & 0x1f); 990344779Sdim else if (F < 64) 991344779Sdim Features2 |= 1U << ((F - 32) & 0x1f); 992344779Sdim else if (F < 96) 993344779Sdim Features3 |= 1U << ((F - 64) & 0x1f); 994344779Sdim else 995344779Sdim llvm_unreachable("Unexpected FeatureBit"); 996344779Sdim }; 997344779Sdim 998321369Sdim if ((EDX >> 15) & 1) 999344779Sdim setFeature(X86::FEATURE_CMOV); 1000321369Sdim if ((EDX >> 23) & 1) 1001344779Sdim setFeature(X86::FEATURE_MMX); 1002321369Sdim if ((EDX >> 25) & 1) 1003344779Sdim setFeature(X86::FEATURE_SSE); 1004321369Sdim if ((EDX >> 26) & 1) 1005344779Sdim setFeature(X86::FEATURE_SSE2); 1006321369Sdim 1007321369Sdim if ((ECX >> 0) & 1) 1008344779Sdim setFeature(X86::FEATURE_SSE3); 1009321369Sdim if ((ECX >> 1) & 1) 1010344779Sdim setFeature(X86::FEATURE_PCLMUL); 1011321369Sdim if ((ECX >> 9) & 1) 1012344779Sdim setFeature(X86::FEATURE_SSSE3); 1013321369Sdim if ((ECX >> 12) & 1) 1014344779Sdim setFeature(X86::FEATURE_FMA); 1015321369Sdim if ((ECX >> 19) & 1) 1016344779Sdim setFeature(X86::FEATURE_SSE4_1); 1017321369Sdim if ((ECX >> 20) & 1) 1018344779Sdim setFeature(X86::FEATURE_SSE4_2); 1019321369Sdim if ((ECX >> 23) & 1) 1020344779Sdim setFeature(X86::FEATURE_POPCNT); 1021321369Sdim if ((ECX >> 25) & 1) 1022344779Sdim setFeature(X86::FEATURE_AES); 1023321369Sdim 1024321369Sdim if ((ECX >> 22) & 1) 1025344779Sdim setFeature(X86::FEATURE_MOVBE); 1026321369Sdim 1027309124Sdim // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 1028309124Sdim // indicates that the AVX registers will be saved and restored on context 1029309124Sdim // switch, then we have full AVX support. 1030309124Sdim const unsigned AVXBits = (1 << 27) | (1 << 28); 1031309124Sdim bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && 1032309124Sdim ((EAX & 0x6) == 0x6); 1033360784Sdim#if defined(__APPLE__) 1034360784Sdim // Darwin lazily saves the AVX512 context on first use: trust that the OS will 1035360784Sdim // save the AVX512 context if we use AVX512 instructions, even the bit is not 1036360784Sdim // set right now. 1037360784Sdim bool HasAVX512Save = true; 1038360784Sdim#else 1039360784Sdim // AVX512 requires additional context to be saved by the OS. 1040309124Sdim bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); 1041360784Sdim#endif 1042321369Sdim 1043321369Sdim if (HasAVX) 1044344779Sdim setFeature(X86::FEATURE_AVX); 1045321369Sdim 1046309124Sdim bool HasLeaf7 = 1047309124Sdim MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 1048309124Sdim 1049321369Sdim if (HasLeaf7 && ((EBX >> 3) & 1)) 1050344779Sdim setFeature(X86::FEATURE_BMI); 1051321369Sdim if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX) 1052344779Sdim setFeature(X86::FEATURE_AVX2); 1053360784Sdim if (HasLeaf7 && ((EBX >> 8) & 1)) 1054344779Sdim setFeature(X86::FEATURE_BMI2); 1055321369Sdim if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) 1056344779Sdim setFeature(X86::FEATURE_AVX512F); 1057321369Sdim if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save) 1058344779Sdim setFeature(X86::FEATURE_AVX512DQ); 1059321369Sdim if (HasLeaf7 && ((EBX >> 19) & 1)) 1060344779Sdim setFeature(X86::FEATURE_ADX); 1061321369Sdim if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save) 1062344779Sdim setFeature(X86::FEATURE_AVX512IFMA); 1063327952Sdim if (HasLeaf7 && ((EBX >> 23) & 1)) 1064344779Sdim setFeature(X86::FEATURE_CLFLUSHOPT); 1065321369Sdim if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save) 1066344779Sdim setFeature(X86::FEATURE_AVX512PF); 1067321369Sdim if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save) 1068344779Sdim setFeature(X86::FEATURE_AVX512ER); 1069321369Sdim if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save) 1070344779Sdim setFeature(X86::FEATURE_AVX512CD); 1071327952Sdim if (HasLeaf7 && ((EBX >> 29) & 1)) 1072344779Sdim setFeature(X86::FEATURE_SHA); 1073321369Sdim if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save) 1074344779Sdim setFeature(X86::FEATURE_AVX512BW); 1075321369Sdim if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save) 1076344779Sdim setFeature(X86::FEATURE_AVX512VL); 1077321369Sdim 1078321369Sdim if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save) 1079344779Sdim setFeature(X86::FEATURE_AVX512VBMI); 1080344779Sdim if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save) 1081344779Sdim setFeature(X86::FEATURE_AVX512VBMI2); 1082344779Sdim if (HasLeaf7 && ((ECX >> 8) & 1)) 1083344779Sdim setFeature(X86::FEATURE_GFNI); 1084344779Sdim if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX) 1085344779Sdim setFeature(X86::FEATURE_VPCLMULQDQ); 1086344779Sdim if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save) 1087344779Sdim setFeature(X86::FEATURE_AVX512VNNI); 1088344779Sdim if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save) 1089344779Sdim setFeature(X86::FEATURE_AVX512BITALG); 1090321369Sdim if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save) 1091344779Sdim setFeature(X86::FEATURE_AVX512VPOPCNTDQ); 1092321369Sdim 1093321369Sdim if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save) 1094344779Sdim setFeature(X86::FEATURE_AVX5124VNNIW); 1095321369Sdim if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save) 1096344779Sdim setFeature(X86::FEATURE_AVX5124FMAPS); 1097360784Sdim if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save) 1098360784Sdim setFeature(X86::FEATURE_AVX512VP2INTERSECT); 1099321369Sdim 1100360784Sdim bool HasLeaf7Subleaf1 = 1101360784Sdim MaxLeaf >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX); 1102360784Sdim if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save) 1103360784Sdim setFeature(X86::FEATURE_AVX512BF16); 1104360784Sdim 1105321369Sdim unsigned MaxExtLevel; 1106321369Sdim getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); 1107321369Sdim 1108321369Sdim bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && 1109321369Sdim !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 1110321369Sdim if (HasExtLeaf1 && ((ECX >> 6) & 1)) 1111344779Sdim setFeature(X86::FEATURE_SSE4_A); 1112321369Sdim if (HasExtLeaf1 && ((ECX >> 11) & 1)) 1113344779Sdim setFeature(X86::FEATURE_XOP); 1114321369Sdim if (HasExtLeaf1 && ((ECX >> 16) & 1)) 1115344779Sdim setFeature(X86::FEATURE_FMA4); 1116321369Sdim 1117321369Sdim if (HasExtLeaf1 && ((EDX >> 29) & 1)) 1118344779Sdim setFeature(X86::FEATURE_EM64T); 1119321369Sdim 1120321369Sdim *FeaturesOut = Features; 1121321369Sdim *Features2Out = Features2; 1122344779Sdim *Features3Out = Features3; 1123309124Sdim} 1124309124Sdim 1125309124SdimStringRef sys::getHostCPUName() { 1126309124Sdim unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 1127309124Sdim unsigned MaxLeaf, Vendor; 1128309124Sdim 1129314564Sdim#if defined(__GNUC__) || defined(__clang__) 1130314564Sdim //FIXME: include cpuid.h from clang or copy __get_cpuid_max here 1131314564Sdim // and simplify it to not invoke __cpuid (like cpu_model.c in 1132314564Sdim // compiler-rt/lib/builtins/cpu_model.c? 1133314564Sdim // Opting for the second option. 1134314564Sdim if(!isCpuIdSupported()) 1135314564Sdim return "generic"; 1136314564Sdim#endif 1137321369Sdim if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1) 1138309124Sdim return "generic"; 1139321369Sdim getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); 1140309124Sdim 1141309124Sdim unsigned Brand_id = EBX & 0xff; 1142309124Sdim unsigned Family = 0, Model = 0; 1143344779Sdim unsigned Features = 0, Features2 = 0, Features3 = 0; 1144309124Sdim detectX86FamilyModel(EAX, &Family, &Model); 1145344779Sdim getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2, &Features3); 1146309124Sdim 1147327952Sdim unsigned Type = 0; 1148327952Sdim unsigned Subtype = 0; 1149309124Sdim 1150309124Sdim if (Vendor == SIG_INTEL) { 1151321369Sdim getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, 1152344779Sdim Features2, Features3, &Type, &Subtype); 1153309124Sdim } else if (Vendor == SIG_AMD) { 1154309124Sdim getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); 1155218885Sdim } 1156327952Sdim 1157327952Sdim // Check subtypes first since those are more specific. 1158327952Sdim#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \ 1159327952Sdim if (Subtype == X86::ENUM) \ 1160327952Sdim return ARCHNAME; 1161327952Sdim#include "llvm/Support/X86TargetParser.def" 1162327952Sdim 1163327952Sdim // Now check types. 1164335799Sdim#define X86_CPU_TYPE(ARCHNAME, ENUM) \ 1165327952Sdim if (Type == X86::ENUM) \ 1166327952Sdim return ARCHNAME; 1167327952Sdim#include "llvm/Support/X86TargetParser.def" 1168327952Sdim 1169218885Sdim return "generic"; 1170218885Sdim} 1171309124Sdim 1172239462Sdim#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) 1173276479SdimStringRef sys::getHostCPUName() { 1174239462Sdim host_basic_info_data_t hostInfo; 1175239462Sdim mach_msg_type_number_t infoCount; 1176239462Sdim 1177239462Sdim infoCount = HOST_BASIC_INFO_COUNT; 1178344779Sdim mach_port_t hostPort = mach_host_self(); 1179344779Sdim host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo, 1180239462Sdim &infoCount); 1181344779Sdim mach_port_deallocate(mach_task_self(), hostPort); 1182239462Sdim 1183309124Sdim if (hostInfo.cpu_type != CPU_TYPE_POWERPC) 1184309124Sdim return "generic"; 1185309124Sdim 1186309124Sdim switch (hostInfo.cpu_subtype) { 1187309124Sdim case CPU_SUBTYPE_POWERPC_601: 1188309124Sdim return "601"; 1189309124Sdim case CPU_SUBTYPE_POWERPC_602: 1190309124Sdim return "602"; 1191309124Sdim case CPU_SUBTYPE_POWERPC_603: 1192309124Sdim return "603"; 1193309124Sdim case CPU_SUBTYPE_POWERPC_603e: 1194309124Sdim return "603e"; 1195309124Sdim case CPU_SUBTYPE_POWERPC_603ev: 1196309124Sdim return "603ev"; 1197309124Sdim case CPU_SUBTYPE_POWERPC_604: 1198309124Sdim return "604"; 1199309124Sdim case CPU_SUBTYPE_POWERPC_604e: 1200309124Sdim return "604e"; 1201309124Sdim case CPU_SUBTYPE_POWERPC_620: 1202309124Sdim return "620"; 1203309124Sdim case CPU_SUBTYPE_POWERPC_750: 1204309124Sdim return "750"; 1205309124Sdim case CPU_SUBTYPE_POWERPC_7400: 1206309124Sdim return "7400"; 1207309124Sdim case CPU_SUBTYPE_POWERPC_7450: 1208309124Sdim return "7450"; 1209309124Sdim case CPU_SUBTYPE_POWERPC_970: 1210309124Sdim return "970"; 1211309124Sdim default:; 1212239462Sdim } 1213309124Sdim 1214239462Sdim return "generic"; 1215239462Sdim} 1216239462Sdim#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__)) 1217276479SdimStringRef sys::getHostCPUName() { 1218321369Sdim std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1219341825Sdim StringRef Content = P ? P->getBuffer() : ""; 1220321369Sdim return detail::getHostCPUNameForPowerPC(Content); 1221239462Sdim} 1222321369Sdim#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) 1223276479SdimStringRef sys::getHostCPUName() { 1224321369Sdim std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1225341825Sdim StringRef Content = P ? P->getBuffer() : ""; 1226321369Sdim return detail::getHostCPUNameForARM(Content); 1227239462Sdim} 1228261991Sdim#elif defined(__linux__) && defined(__s390x__) 1229276479SdimStringRef sys::getHostCPUName() { 1230321369Sdim std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1231341825Sdim StringRef Content = P ? P->getBuffer() : ""; 1232321369Sdim return detail::getHostCPUNameForS390x(Content); 1233261991Sdim} 1234360784Sdim#elif defined(__APPLE__) && defined(__aarch64__) 1235360784SdimStringRef sys::getHostCPUName() { 1236360784Sdim return "cyclone"; 1237360784Sdim} 1238360784Sdim#elif defined(__APPLE__) && defined(__arm__) 1239360784SdimStringRef sys::getHostCPUName() { 1240360784Sdim host_basic_info_data_t hostInfo; 1241360784Sdim mach_msg_type_number_t infoCount; 1242360784Sdim 1243360784Sdim infoCount = HOST_BASIC_INFO_COUNT; 1244360784Sdim mach_port_t hostPort = mach_host_self(); 1245360784Sdim host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo, 1246360784Sdim &infoCount); 1247360784Sdim mach_port_deallocate(mach_task_self(), hostPort); 1248360784Sdim 1249360784Sdim if (hostInfo.cpu_type != CPU_TYPE_ARM) { 1250360784Sdim assert(false && "CPUType not equal to ARM should not be possible on ARM"); 1251360784Sdim return "generic"; 1252360784Sdim } 1253360784Sdim switch (hostInfo.cpu_subtype) { 1254360784Sdim case CPU_SUBTYPE_ARM_V7S: 1255360784Sdim return "swift"; 1256360784Sdim default:; 1257360784Sdim } 1258360784Sdim 1259360784Sdim return "generic"; 1260360784Sdim} 1261218885Sdim#else 1262309124SdimStringRef sys::getHostCPUName() { return "generic"; } 1263218885Sdim#endif 1264218885Sdim 1265314564Sdim#if defined(__linux__) && defined(__x86_64__) 1266314564Sdim// On Linux, the number of physical cores can be computed from /proc/cpuinfo, 1267314564Sdim// using the number of unique physical/core id pairs. The following 1268314564Sdim// implementation reads the /proc/cpuinfo format on an x86_64 system. 1269314564Sdimstatic int computeHostNumPhysicalCores() { 1270314564Sdim // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be 1271314564Sdim // mmapped because it appears to have 0 size. 1272314564Sdim llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 1273314564Sdim llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); 1274314564Sdim if (std::error_code EC = Text.getError()) { 1275314564Sdim llvm::errs() << "Can't read " 1276314564Sdim << "/proc/cpuinfo: " << EC.message() << "\n"; 1277321369Sdim return -1; 1278314564Sdim } 1279314564Sdim SmallVector<StringRef, 8> strs; 1280314564Sdim (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, 1281314564Sdim /*KeepEmpty=*/false); 1282314564Sdim int CurPhysicalId = -1; 1283314564Sdim int CurCoreId = -1; 1284314564Sdim SmallSet<std::pair<int, int>, 32> UniqueItems; 1285314564Sdim for (auto &Line : strs) { 1286314564Sdim Line = Line.trim(); 1287314564Sdim if (!Line.startswith("physical id") && !Line.startswith("core id")) 1288314564Sdim continue; 1289314564Sdim std::pair<StringRef, StringRef> Data = Line.split(':'); 1290314564Sdim auto Name = Data.first.trim(); 1291314564Sdim auto Val = Data.second.trim(); 1292314564Sdim if (Name == "physical id") { 1293314564Sdim assert(CurPhysicalId == -1 && 1294314564Sdim "Expected a core id before seeing another physical id"); 1295314564Sdim Val.getAsInteger(10, CurPhysicalId); 1296314564Sdim } 1297314564Sdim if (Name == "core id") { 1298314564Sdim assert(CurCoreId == -1 && 1299314564Sdim "Expected a physical id before seeing another core id"); 1300314564Sdim Val.getAsInteger(10, CurCoreId); 1301314564Sdim } 1302314564Sdim if (CurPhysicalId != -1 && CurCoreId != -1) { 1303314564Sdim UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId)); 1304314564Sdim CurPhysicalId = -1; 1305314564Sdim CurCoreId = -1; 1306314564Sdim } 1307314564Sdim } 1308314564Sdim return UniqueItems.size(); 1309314564Sdim} 1310314564Sdim#elif defined(__APPLE__) && defined(__x86_64__) 1311314564Sdim#include <sys/param.h> 1312314564Sdim#include <sys/sysctl.h> 1313314564Sdim 1314314564Sdim// Gets the number of *physical cores* on the machine. 1315314564Sdimstatic int computeHostNumPhysicalCores() { 1316314564Sdim uint32_t count; 1317314564Sdim size_t len = sizeof(count); 1318314564Sdim sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0); 1319314564Sdim if (count < 1) { 1320314564Sdim int nm[2]; 1321314564Sdim nm[0] = CTL_HW; 1322314564Sdim nm[1] = HW_AVAILCPU; 1323314564Sdim sysctl(nm, 2, &count, &len, NULL, 0); 1324314564Sdim if (count < 1) 1325314564Sdim return -1; 1326314564Sdim } 1327314564Sdim return count; 1328314564Sdim} 1329314564Sdim#else 1330314564Sdim// On other systems, return -1 to indicate unknown. 1331314564Sdimstatic int computeHostNumPhysicalCores() { return -1; } 1332314564Sdim#endif 1333314564Sdim 1334314564Sdimint sys::getHostNumPhysicalCores() { 1335314564Sdim static int NumCores = computeHostNumPhysicalCores(); 1336314564Sdim return NumCores; 1337314564Sdim} 1338314564Sdim 1339314564Sdim#if defined(__i386__) || defined(_M_IX86) || \ 1340314564Sdim defined(__x86_64__) || defined(_M_X64) 1341249423Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { 1342288943Sdim unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 1343288943Sdim unsigned MaxLevel; 1344288943Sdim union { 1345288943Sdim unsigned u[3]; 1346309124Sdim char c[12]; 1347288943Sdim } text; 1348288943Sdim 1349309124Sdim if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) || 1350288943Sdim MaxLevel < 1) 1351288943Sdim return false; 1352288943Sdim 1353309124Sdim getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); 1354288943Sdim 1355353358Sdim Features["cx8"] = (EDX >> 8) & 1; 1356327952Sdim Features["cmov"] = (EDX >> 15) & 1; 1357327952Sdim Features["mmx"] = (EDX >> 23) & 1; 1358353358Sdim Features["fxsr"] = (EDX >> 24) & 1; 1359327952Sdim Features["sse"] = (EDX >> 25) & 1; 1360327952Sdim Features["sse2"] = (EDX >> 26) & 1; 1361327952Sdim 1362327952Sdim Features["sse3"] = (ECX >> 0) & 1; 1363327952Sdim Features["pclmul"] = (ECX >> 1) & 1; 1364327952Sdim Features["ssse3"] = (ECX >> 9) & 1; 1365327952Sdim Features["cx16"] = (ECX >> 13) & 1; 1366288943Sdim Features["sse4.1"] = (ECX >> 19) & 1; 1367288943Sdim Features["sse4.2"] = (ECX >> 20) & 1; 1368327952Sdim Features["movbe"] = (ECX >> 22) & 1; 1369288943Sdim Features["popcnt"] = (ECX >> 23) & 1; 1370327952Sdim Features["aes"] = (ECX >> 25) & 1; 1371327952Sdim Features["rdrnd"] = (ECX >> 30) & 1; 1372288943Sdim 1373288943Sdim // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 1374288943Sdim // indicates that the AVX registers will be saved and restored on context 1375288943Sdim // switch, then we have full AVX support. 1376296417Sdim bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) && 1377309124Sdim !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6); 1378360784Sdim#if defined(__APPLE__) 1379360784Sdim // Darwin lazily saves the AVX512 context on first use: trust that the OS will 1380360784Sdim // save the AVX512 context if we use AVX512 instructions, even the bit is not 1381360784Sdim // set right now. 1382360784Sdim bool HasAVX512Save = true; 1383360784Sdim#else 1384327952Sdim // AVX512 requires additional context to be saved by the OS. 1385327952Sdim bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); 1386360784Sdim#endif 1387288943Sdim 1388327952Sdim Features["avx"] = HasAVXSave; 1389327952Sdim Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave; 1390296417Sdim // Only enable XSAVE if OS has enabled support for saving YMM state. 1391327952Sdim Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave; 1392327952Sdim Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave; 1393296417Sdim 1394288943Sdim unsigned MaxExtLevel; 1395309124Sdim getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); 1396288943Sdim 1397288943Sdim bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && 1398309124Sdim !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 1399341825Sdim Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1); 1400327952Sdim Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1); 1401327952Sdim Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1); 1402327952Sdim Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1); 1403327952Sdim Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; 1404327952Sdim Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1); 1405327952Sdim Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; 1406327952Sdim Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); 1407309124Sdim Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1); 1408288943Sdim 1409344779Sdim Features["64bit"] = HasExtLeaf1 && ((EDX >> 29) & 1); 1410344779Sdim 1411341825Sdim // Miscellaneous memory related features, detected by 1412341825Sdim // using the 0x80000008 leaf of the CPUID instruction 1413321369Sdim bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 && 1414327952Sdim !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX); 1415341825Sdim Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1); 1416341825Sdim Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1); 1417321369Sdim 1418309124Sdim bool HasLeaf7 = 1419309124Sdim MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 1420288943Sdim 1421327952Sdim Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); 1422327952Sdim Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1); 1423327952Sdim Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); 1424288943Sdim // AVX2 is only supported if we have the OS save support from AVX. 1425327952Sdim Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave; 1426327952Sdim Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1); 1427341825Sdim Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1); 1428327952Sdim Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1); 1429288943Sdim // AVX512 is only supported if the OS supports the context save for it. 1430327952Sdim Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; 1431327952Sdim Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save; 1432327952Sdim Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); 1433327952Sdim Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); 1434309124Sdim Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save; 1435327952Sdim Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1); 1436327952Sdim Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1); 1437327952Sdim Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save; 1438327952Sdim Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save; 1439327952Sdim Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save; 1440327952Sdim Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); 1441327952Sdim Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; 1442327952Sdim Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; 1443288943Sdim 1444327952Sdim Features["prefetchwt1"] = HasLeaf7 && ((ECX >> 0) & 1); 1445327952Sdim Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save; 1446327952Sdim Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); 1447341825Sdim Features["waitpkg"] = HasLeaf7 && ((ECX >> 5) & 1); 1448327952Sdim Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save; 1449327952Sdim Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1); 1450327952Sdim Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1); 1451327952Sdim Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave; 1452327952Sdim Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave; 1453327952Sdim Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save; 1454327952Sdim Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save; 1455327952Sdim Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save; 1456341825Sdim Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1); 1457341825Sdim Features["cldemote"] = HasLeaf7 && ((ECX >> 25) & 1); 1458341825Sdim Features["movdiri"] = HasLeaf7 && ((ECX >> 27) & 1); 1459341825Sdim Features["movdir64b"] = HasLeaf7 && ((ECX >> 28) & 1); 1460353358Sdim Features["enqcmd"] = HasLeaf7 && ((ECX >> 29) & 1); 1461309124Sdim 1462341825Sdim // There are two CPUID leafs which information associated with the pconfig 1463341825Sdim // instruction: 1464341825Sdim // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th 1465341825Sdim // bit of EDX), while the EAX=0x1b leaf returns information on the 1466341825Sdim // availability of specific pconfig leafs. 1467341825Sdim // The target feature here only refers to the the first of these two. 1468341825Sdim // Users might need to check for the availability of specific pconfig 1469341825Sdim // leaves using cpuid, since that information is ignored while 1470341825Sdim // detecting features using the "-march=native" flag. 1471341825Sdim // For more info, see X86 ISA docs. 1472341825Sdim Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1); 1473353358Sdim bool HasLeaf7Subleaf1 = 1474353358Sdim MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX); 1475353358Sdim Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save; 1476341825Sdim 1477296417Sdim bool HasLeafD = MaxLevel >= 0xd && 1478309124Sdim !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); 1479296417Sdim 1480296417Sdim // Only enable XSAVE if OS has enabled support for saving YMM state. 1481327952Sdim Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave; 1482327952Sdim Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave; 1483327952Sdim Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave; 1484296417Sdim 1485341825Sdim bool HasLeaf14 = MaxLevel >= 0x14 && 1486341825Sdim !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX); 1487341825Sdim 1488341825Sdim Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1); 1489341825Sdim 1490288943Sdim return true; 1491288943Sdim} 1492288943Sdim#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) 1493288943Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { 1494321369Sdim std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1495321369Sdim if (!P) 1496280031Sdim return false; 1497249423Sdim 1498249423Sdim SmallVector<StringRef, 32> Lines; 1499321369Sdim P->getBuffer().split(Lines, "\n"); 1500249423Sdim 1501261991Sdim SmallVector<StringRef, 32> CPUFeatures; 1502261991Sdim 1503261991Sdim // Look for the CPU features. 1504249423Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 1505261991Sdim if (Lines[I].startswith("Features")) { 1506296417Sdim Lines[I].split(CPUFeatures, ' '); 1507261991Sdim break; 1508261991Sdim } 1509249423Sdim 1510276479Sdim#if defined(__aarch64__) 1511276479Sdim // Keep track of which crypto features we have seen 1512309124Sdim enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 }; 1513276479Sdim uint32_t crypto = 0; 1514276479Sdim#endif 1515276479Sdim 1516261991Sdim for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 1517261991Sdim StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) 1518276479Sdim#if defined(__aarch64__) 1519309124Sdim .Case("asimd", "neon") 1520309124Sdim .Case("fp", "fp-armv8") 1521309124Sdim .Case("crc32", "crc") 1522276479Sdim#else 1523309124Sdim .Case("half", "fp16") 1524309124Sdim .Case("neon", "neon") 1525309124Sdim .Case("vfpv3", "vfp3") 1526309124Sdim .Case("vfpv3d16", "d16") 1527309124Sdim .Case("vfpv4", "vfp4") 1528309124Sdim .Case("idiva", "hwdiv-arm") 1529309124Sdim .Case("idivt", "hwdiv") 1530276479Sdim#endif 1531309124Sdim .Default(""); 1532249423Sdim 1533276479Sdim#if defined(__aarch64__) 1534276479Sdim // We need to check crypto separately since we need all of the crypto 1535276479Sdim // extensions to enable the subtarget feature 1536276479Sdim if (CPUFeatures[I] == "aes") 1537276479Sdim crypto |= CAP_AES; 1538276479Sdim else if (CPUFeatures[I] == "pmull") 1539276479Sdim crypto |= CAP_PMULL; 1540276479Sdim else if (CPUFeatures[I] == "sha1") 1541276479Sdim crypto |= CAP_SHA1; 1542276479Sdim else if (CPUFeatures[I] == "sha2") 1543276479Sdim crypto |= CAP_SHA2; 1544276479Sdim#endif 1545276479Sdim 1546261991Sdim if (LLVMFeatureStr != "") 1547280031Sdim Features[LLVMFeatureStr] = true; 1548249423Sdim } 1549249423Sdim 1550276479Sdim#if defined(__aarch64__) 1551276479Sdim // If we have all crypto bits we can add the feature 1552276479Sdim if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) 1553280031Sdim Features["crypto"] = true; 1554276479Sdim#endif 1555276479Sdim 1556261991Sdim return true; 1557249423Sdim} 1558360784Sdim#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64)) 1559360784Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { 1560360784Sdim if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) 1561360784Sdim Features["neon"] = true; 1562360784Sdim if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) 1563360784Sdim Features["crc"] = true; 1564360784Sdim if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) 1565360784Sdim Features["crypto"] = true; 1566360784Sdim 1567360784Sdim return true; 1568360784Sdim} 1569249423Sdim#else 1570309124Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; } 1571249423Sdim#endif 1572249423Sdim 1573249423Sdimstd::string sys::getProcessTriple() { 1574321369Sdim std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE); 1575321369Sdim Triple PT(Triple::normalize(TargetTripleString)); 1576249423Sdim 1577249423Sdim if (sizeof(void *) == 8 && PT.isArch32Bit()) 1578249423Sdim PT = PT.get64BitArchVariant(); 1579249423Sdim if (sizeof(void *) == 4 && PT.isArch64Bit()) 1580249423Sdim PT = PT.get32BitArchVariant(); 1581249423Sdim 1582249423Sdim return PT.str(); 1583249423Sdim} 1584