Path: blob/main/contrib/llvm-project/llvm/lib/TargetParser/Host.cpp
35234 views
//===-- Host.cpp - Implement OS Host Detection ------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the operating system Host detection.9//10//===----------------------------------------------------------------------===//1112#include "llvm/TargetParser/Host.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringMap.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/StringSwitch.h"17#include "llvm/Config/llvm-config.h"18#include "llvm/Support/MemoryBuffer.h"19#include "llvm/Support/raw_ostream.h"20#include "llvm/TargetParser/Triple.h"21#include "llvm/TargetParser/X86TargetParser.h"22#include <string.h>2324// Include the platform-specific parts of this class.25#ifdef LLVM_ON_UNIX26#include "Unix/Host.inc"27#include <sched.h>28#endif29#ifdef _WIN3230#include "Windows/Host.inc"31#endif32#ifdef _MSC_VER33#include <intrin.h>34#endif35#ifdef __MVS__36#include "llvm/Support/BCD.h"37#endif38#if defined(__APPLE__)39#include <mach/host_info.h>40#include <mach/mach.h>41#include <mach/mach_host.h>42#include <mach/machine.h>43#include <sys/param.h>44#include <sys/sysctl.h>45#endif46#ifdef _AIX47#include <sys/systemcfg.h>48#endif49#if defined(__sun__) && defined(__svr4__)50#include <kstat.h>51#endif5253#define DEBUG_TYPE "host-detection"5455//===----------------------------------------------------------------------===//56//57// Implementations of the CPU detection routines58//59//===----------------------------------------------------------------------===//6061using namespace llvm;6263static std::unique_ptr<llvm::MemoryBuffer>64LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {65llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =66llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");67if (std::error_code EC = Text.getError()) {68llvm::errs() << "Can't read "69<< "/proc/cpuinfo: " << EC.message() << "\n";70return nullptr;71}72return std::move(*Text);73}7475StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {76// Access to the Processor Version Register (PVR) on PowerPC is privileged,77// and so we must use an operating-system interface to determine the current78// processor type. On Linux, this is exposed through the /proc/cpuinfo file.79const char *generic = "generic";8081// The cpu line is second (after the 'processor: 0' line), so if this82// buffer is too small then something has changed (or is wrong).83StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();84StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();8586StringRef::const_iterator CIP = CPUInfoStart;8788StringRef::const_iterator CPUStart = nullptr;89size_t CPULen = 0;9091// We need to find the first line which starts with cpu, spaces, and a colon.92// After the colon, there may be some additional spaces and then the cpu type.93while (CIP < CPUInfoEnd && CPUStart == nullptr) {94if (CIP < CPUInfoEnd && *CIP == '\n')95++CIP;9697if (CIP < CPUInfoEnd && *CIP == 'c') {98++CIP;99if (CIP < CPUInfoEnd && *CIP == 'p') {100++CIP;101if (CIP < CPUInfoEnd && *CIP == 'u') {102++CIP;103while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))104++CIP;105106if (CIP < CPUInfoEnd && *CIP == ':') {107++CIP;108while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))109++CIP;110111if (CIP < CPUInfoEnd) {112CPUStart = CIP;113while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&114*CIP != ',' && *CIP != '\n'))115++CIP;116CPULen = CIP - CPUStart;117}118}119}120}121}122123if (CPUStart == nullptr)124while (CIP < CPUInfoEnd && *CIP != '\n')125++CIP;126}127128if (CPUStart == nullptr)129return generic;130131return StringSwitch<const char *>(StringRef(CPUStart, CPULen))132.Case("604e", "604e")133.Case("604", "604")134.Case("7400", "7400")135.Case("7410", "7400")136.Case("7447", "7400")137.Case("7455", "7450")138.Case("G4", "g4")139.Case("POWER4", "970")140.Case("PPC970FX", "970")141.Case("PPC970MP", "970")142.Case("G5", "g5")143.Case("POWER5", "g5")144.Case("A2", "a2")145.Case("POWER6", "pwr6")146.Case("POWER7", "pwr7")147.Case("POWER8", "pwr8")148.Case("POWER8E", "pwr8")149.Case("POWER8NVL", "pwr8")150.Case("POWER9", "pwr9")151.Case("POWER10", "pwr10")152.Case("POWER11", "pwr11")153// FIXME: If we get a simulator or machine with the capabilities of154// mcpu=future, we should revisit this and add the name reported by the155// simulator/machine.156.Default(generic);157}158159StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {160// The cpuid register on arm is not accessible from user space. On Linux,161// it is exposed through the /proc/cpuinfo file.162163// Read 32 lines from /proc/cpuinfo, which should contain the CPU part line164// in all cases.165SmallVector<StringRef, 32> Lines;166ProcCpuinfoContent.split(Lines, "\n");167168// Look for the CPU implementer line.169StringRef Implementer;170StringRef Hardware;171StringRef Part;172for (unsigned I = 0, E = Lines.size(); I != E; ++I) {173if (Lines[I].starts_with("CPU implementer"))174Implementer = Lines[I].substr(15).ltrim("\t :");175if (Lines[I].starts_with("Hardware"))176Hardware = Lines[I].substr(8).ltrim("\t :");177if (Lines[I].starts_with("CPU part"))178Part = Lines[I].substr(8).ltrim("\t :");179}180181if (Implementer == "0x41") { // ARM Ltd.182// MSM8992/8994 may give cpu part for the core that the kernel is running on,183// which is undeterministic and wrong. Always return cortex-a53 for these SoC.184if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996"))185return "cortex-a53";186187188// The CPU part is a 3 digit hexadecimal number with a 0x prefix. The189// values correspond to the "Part number" in the CP15/c0 register. The190// contents are specified in the various processor manuals.191// This corresponds to the Main ID Register in Technical Reference Manuals.192// and is used in programs like sys-utils193return StringSwitch<const char *>(Part)194.Case("0x926", "arm926ej-s")195.Case("0xb02", "mpcore")196.Case("0xb36", "arm1136j-s")197.Case("0xb56", "arm1156t2-s")198.Case("0xb76", "arm1176jz-s")199.Case("0xc05", "cortex-a5")200.Case("0xc07", "cortex-a7")201.Case("0xc08", "cortex-a8")202.Case("0xc09", "cortex-a9")203.Case("0xc0f", "cortex-a15")204.Case("0xc0e", "cortex-a17")205.Case("0xc20", "cortex-m0")206.Case("0xc23", "cortex-m3")207.Case("0xc24", "cortex-m4")208.Case("0xc27", "cortex-m7")209.Case("0xd20", "cortex-m23")210.Case("0xd21", "cortex-m33")211.Case("0xd24", "cortex-m52")212.Case("0xd22", "cortex-m55")213.Case("0xd23", "cortex-m85")214.Case("0xc18", "cortex-r8")215.Case("0xd13", "cortex-r52")216.Case("0xd16", "cortex-r52plus")217.Case("0xd15", "cortex-r82")218.Case("0xd14", "cortex-r82ae")219.Case("0xd02", "cortex-a34")220.Case("0xd04", "cortex-a35")221.Case("0xd03", "cortex-a53")222.Case("0xd05", "cortex-a55")223.Case("0xd46", "cortex-a510")224.Case("0xd80", "cortex-a520")225.Case("0xd88", "cortex-a520ae")226.Case("0xd07", "cortex-a57")227.Case("0xd06", "cortex-a65")228.Case("0xd43", "cortex-a65ae")229.Case("0xd08", "cortex-a72")230.Case("0xd09", "cortex-a73")231.Case("0xd0a", "cortex-a75")232.Case("0xd0b", "cortex-a76")233.Case("0xd0e", "cortex-a76ae")234.Case("0xd0d", "cortex-a77")235.Case("0xd41", "cortex-a78")236.Case("0xd42", "cortex-a78ae")237.Case("0xd4b", "cortex-a78c")238.Case("0xd47", "cortex-a710")239.Case("0xd4d", "cortex-a715")240.Case("0xd81", "cortex-a720")241.Case("0xd89", "cortex-a720ae")242.Case("0xd87", "cortex-a725")243.Case("0xd44", "cortex-x1")244.Case("0xd4c", "cortex-x1c")245.Case("0xd48", "cortex-x2")246.Case("0xd4e", "cortex-x3")247.Case("0xd82", "cortex-x4")248.Case("0xd85", "cortex-x925")249.Case("0xd4a", "neoverse-e1")250.Case("0xd0c", "neoverse-n1")251.Case("0xd49", "neoverse-n2")252.Case("0xd8e", "neoverse-n3")253.Case("0xd40", "neoverse-v1")254.Case("0xd4f", "neoverse-v2")255.Case("0xd84", "neoverse-v3")256.Case("0xd83", "neoverse-v3ae")257.Default("generic");258}259260if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.261return StringSwitch<const char *>(Part)262.Case("0x516", "thunderx2t99")263.Case("0x0516", "thunderx2t99")264.Case("0xaf", "thunderx2t99")265.Case("0x0af", "thunderx2t99")266.Case("0xa1", "thunderxt88")267.Case("0x0a1", "thunderxt88")268.Default("generic");269}270271if (Implementer == "0x46") { // Fujitsu Ltd.272return StringSwitch<const char *>(Part)273.Case("0x001", "a64fx")274.Default("generic");275}276277if (Implementer == "0x4e") { // NVIDIA Corporation278return StringSwitch<const char *>(Part)279.Case("0x004", "carmel")280.Default("generic");281}282283if (Implementer == "0x48") // HiSilicon Technologies, Inc.284// The CPU part is a 3 digit hexadecimal number with a 0x prefix. The285// values correspond to the "Part number" in the CP15/c0 register. The286// contents are specified in the various processor manuals.287return StringSwitch<const char *>(Part)288.Case("0xd01", "tsv110")289.Default("generic");290291if (Implementer == "0x51") // Qualcomm Technologies, Inc.292// The CPU part is a 3 digit hexadecimal number with a 0x prefix. The293// values correspond to the "Part number" in the CP15/c0 register. The294// contents are specified in the various processor manuals.295return StringSwitch<const char *>(Part)296.Case("0x06f", "krait") // APQ8064297.Case("0x201", "kryo")298.Case("0x205", "kryo")299.Case("0x211", "kryo")300.Case("0x800", "cortex-a73") // Kryo 2xx Gold301.Case("0x801", "cortex-a73") // Kryo 2xx Silver302.Case("0x802", "cortex-a75") // Kryo 3xx Gold303.Case("0x803", "cortex-a75") // Kryo 3xx Silver304.Case("0x804", "cortex-a76") // Kryo 4xx Gold305.Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver306.Case("0xc00", "falkor")307.Case("0xc01", "saphira")308.Case("0x001", "oryon-1")309.Default("generic");310if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.311// The Exynos chips have a convoluted ID scheme that doesn't seem to follow312// any predictive pattern across variants and parts.313unsigned Variant = 0, Part = 0;314315// Look for the CPU variant line, whose value is a 1 digit hexadecimal316// number, corresponding to the Variant bits in the CP15/C0 register.317for (auto I : Lines)318if (I.consume_front("CPU variant"))319I.ltrim("\t :").getAsInteger(0, Variant);320321// Look for the CPU part line, whose value is a 3 digit hexadecimal322// number, corresponding to the PartNum bits in the CP15/C0 register.323for (auto I : Lines)324if (I.consume_front("CPU part"))325I.ltrim("\t :").getAsInteger(0, Part);326327unsigned Exynos = (Variant << 12) | Part;328switch (Exynos) {329default:330// Default by falling through to Exynos M3.331[[fallthrough]];332case 0x1002:333return "exynos-m3";334case 0x1003:335return "exynos-m4";336}337}338339if (Implementer == "0x6d") { // Microsoft Corporation.340// The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2.341return StringSwitch<const char *>(Part)342.Case("0xd49", "neoverse-n2")343.Default("generic");344}345346if (Implementer == "0xc0") { // Ampere Computing347return StringSwitch<const char *>(Part)348.Case("0xac3", "ampere1")349.Case("0xac4", "ampere1a")350.Case("0xac5", "ampere1b")351.Default("generic");352}353354return "generic";355}356357namespace {358StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {359switch (Id) {360case 2064: // z900 not supported by LLVM361case 2066:362case 2084: // z990 not supported by LLVM363case 2086:364case 2094: // z9-109 not supported by LLVM365case 2096:366return "generic";367case 2097:368case 2098:369return "z10";370case 2817:371case 2818:372return "z196";373case 2827:374case 2828:375return "zEC12";376case 2964:377case 2965:378return HaveVectorSupport? "z13" : "zEC12";379case 3906:380case 3907:381return HaveVectorSupport? "z14" : "zEC12";382case 8561:383case 8562:384return HaveVectorSupport? "z15" : "zEC12";385case 3931:386case 3932:387default:388return HaveVectorSupport? "z16" : "zEC12";389}390}391} // end anonymous namespace392393StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {394// STIDP is a privileged operation, so use /proc/cpuinfo instead.395396// The "processor 0:" line comes after a fair amount of other information,397// including a cache breakdown, but this should be plenty.398SmallVector<StringRef, 32> Lines;399ProcCpuinfoContent.split(Lines, "\n");400401// Look for the CPU features.402SmallVector<StringRef, 32> CPUFeatures;403for (unsigned I = 0, E = Lines.size(); I != E; ++I)404if (Lines[I].starts_with("features")) {405size_t Pos = Lines[I].find(':');406if (Pos != StringRef::npos) {407Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');408break;409}410}411412// We need to check for the presence of vector support independently of413// the machine type, since we may only use the vector register set when414// supported by the kernel (and hypervisor).415bool HaveVectorSupport = false;416for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {417if (CPUFeatures[I] == "vx")418HaveVectorSupport = true;419}420421// Now check the processor machine type.422for (unsigned I = 0, E = Lines.size(); I != E; ++I) {423if (Lines[I].starts_with("processor ")) {424size_t Pos = Lines[I].find("machine = ");425if (Pos != StringRef::npos) {426Pos += sizeof("machine = ") - 1;427unsigned int Id;428if (!Lines[I].drop_front(Pos).getAsInteger(10, Id))429return getCPUNameFromS390Model(Id, HaveVectorSupport);430}431break;432}433}434435return "generic";436}437438StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {439// There are 24 lines in /proc/cpuinfo440SmallVector<StringRef> Lines;441ProcCpuinfoContent.split(Lines, "\n");442443// Look for uarch line to determine cpu name444StringRef UArch;445for (unsigned I = 0, E = Lines.size(); I != E; ++I) {446if (Lines[I].starts_with("uarch")) {447UArch = Lines[I].substr(5).ltrim("\t :");448break;449}450}451452return StringSwitch<const char *>(UArch)453.Case("sifive,u74-mc", "sifive-u74")454.Case("sifive,bullet0", "sifive-u74")455.Default("");456}457458StringRef sys::detail::getHostCPUNameForBPF() {459#if !defined(__linux__) || !defined(__x86_64__)460return "generic";461#else462uint8_t v3_insns[40] __attribute__ ((aligned (8))) =463/* BPF_MOV64_IMM(BPF_REG_0, 0) */464{ 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,465/* BPF_MOV64_IMM(BPF_REG_2, 1) */4660xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,467/* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */4680xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,469/* BPF_MOV64_IMM(BPF_REG_0, 1) */4700xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,471/* BPF_EXIT_INSN() */4720x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };473474uint8_t v2_insns[40] __attribute__ ((aligned (8))) =475/* BPF_MOV64_IMM(BPF_REG_0, 0) */476{ 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,477/* BPF_MOV64_IMM(BPF_REG_2, 1) */4780xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,479/* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */4800xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,481/* BPF_MOV64_IMM(BPF_REG_0, 1) */4820xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,483/* BPF_EXIT_INSN() */4840x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };485486struct bpf_prog_load_attr {487uint32_t prog_type;488uint32_t insn_cnt;489uint64_t insns;490uint64_t license;491uint32_t log_level;492uint32_t log_size;493uint64_t log_buf;494uint32_t kern_version;495uint32_t prog_flags;496} attr = {};497attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */498attr.insn_cnt = 5;499attr.insns = (uint64_t)v3_insns;500attr.license = (uint64_t)"DUMMY";501502int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,503sizeof(attr));504if (fd >= 0) {505close(fd);506return "v3";507}508509/* Clear the whole attr in case its content changed by syscall. */510memset(&attr, 0, sizeof(attr));511attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */512attr.insn_cnt = 5;513attr.insns = (uint64_t)v2_insns;514attr.license = (uint64_t)"DUMMY";515fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));516if (fd >= 0) {517close(fd);518return "v2";519}520return "v1";521#endif522}523524#if defined(__i386__) || defined(_M_IX86) || \525defined(__x86_64__) || defined(_M_X64)526527// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).528// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID529// support. Consequently, for i386, the presence of CPUID is checked first530// via the corresponding eflags bit.531// Removal of cpuid.h header motivated by PR30384532// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp533// or test-suite, but are used in external projects e.g. libstdcxx534static bool isCpuIdSupported() {535#if defined(__GNUC__) || defined(__clang__)536#if defined(__i386__)537int __cpuid_supported;538__asm__(" pushfl\n"539" popl %%eax\n"540" movl %%eax,%%ecx\n"541" xorl $0x00200000,%%eax\n"542" pushl %%eax\n"543" popfl\n"544" pushfl\n"545" popl %%eax\n"546" movl $0,%0\n"547" cmpl %%eax,%%ecx\n"548" je 1f\n"549" movl $1,%0\n"550"1:"551: "=r"(__cpuid_supported)552:553: "eax", "ecx");554if (!__cpuid_supported)555return false;556#endif557return true;558#endif559return true;560}561562/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in563/// the specified arguments. If we can't run cpuid on the host, return true.564static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,565unsigned *rECX, unsigned *rEDX) {566#if defined(__GNUC__) || defined(__clang__)567#if defined(__x86_64__)568// gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.569// FIXME: should we save this for Clang?570__asm__("movq\t%%rbx, %%rsi\n\t"571"cpuid\n\t"572"xchgq\t%%rbx, %%rsi\n\t"573: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)574: "a"(value));575return false;576#elif defined(__i386__)577__asm__("movl\t%%ebx, %%esi\n\t"578"cpuid\n\t"579"xchgl\t%%ebx, %%esi\n\t"580: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)581: "a"(value));582return false;583#else584return true;585#endif586#elif defined(_MSC_VER)587// The MSVC intrinsic is portable across x86 and x64.588int registers[4];589__cpuid(registers, value);590*rEAX = registers[0];591*rEBX = registers[1];592*rECX = registers[2];593*rEDX = registers[3];594return false;595#else596return true;597#endif598}599600namespace llvm {601namespace sys {602namespace detail {603namespace x86 {604605VendorSignatures getVendorSignature(unsigned *MaxLeaf) {606unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;607if (MaxLeaf == nullptr)608MaxLeaf = &EAX;609else610*MaxLeaf = 0;611612if (!isCpuIdSupported())613return VendorSignatures::UNKNOWN;614615if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)616return VendorSignatures::UNKNOWN;617618// "Genu ineI ntel"619if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)620return VendorSignatures::GENUINE_INTEL;621622// "Auth enti cAMD"623if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)624return VendorSignatures::AUTHENTIC_AMD;625626return VendorSignatures::UNKNOWN;627}628629} // namespace x86630} // namespace detail631} // namespace sys632} // namespace llvm633634using namespace llvm::sys::detail::x86;635636/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return637/// the 4 values in the specified arguments. If we can't run cpuid on the host,638/// return true.639static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,640unsigned *rEAX, unsigned *rEBX, unsigned *rECX,641unsigned *rEDX) {642#if defined(__GNUC__) || defined(__clang__)643#if defined(__x86_64__)644// gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.645// FIXME: should we save this for Clang?646__asm__("movq\t%%rbx, %%rsi\n\t"647"cpuid\n\t"648"xchgq\t%%rbx, %%rsi\n\t"649: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)650: "a"(value), "c"(subleaf));651return false;652#elif defined(__i386__)653__asm__("movl\t%%ebx, %%esi\n\t"654"cpuid\n\t"655"xchgl\t%%ebx, %%esi\n\t"656: "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)657: "a"(value), "c"(subleaf));658return false;659#else660return true;661#endif662#elif defined(_MSC_VER)663int registers[4];664__cpuidex(registers, value, subleaf);665*rEAX = registers[0];666*rEBX = registers[1];667*rECX = registers[2];668*rEDX = registers[3];669return false;670#else671return true;672#endif673}674675// Read control register 0 (XCR0). Used to detect features such as AVX.676static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {677#if defined(__GNUC__) || defined(__clang__)678// Check xgetbv; this uses a .byte sequence instead of the instruction679// directly because older assemblers do not include support for xgetbv and680// there is no easy way to conditionally compile based on the assembler used.681__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));682return false;683#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)684unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);685*rEAX = Result;686*rEDX = Result >> 32;687return false;688#else689return true;690#endif691}692693static void detectX86FamilyModel(unsigned EAX, unsigned *Family,694unsigned *Model) {695*Family = (EAX >> 8) & 0xf; // Bits 8 - 11696*Model = (EAX >> 4) & 0xf; // Bits 4 - 7697if (*Family == 6 || *Family == 0xf) {698if (*Family == 0xf)699// Examine extended family ID if family ID is F.700*Family += (EAX >> 20) & 0xff; // Bits 20 - 27701// Examine extended model ID if family ID is 6 or F.702*Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19703}704}705706#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0707708static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,709unsigned Model,710const unsigned *Features,711unsigned *Type,712unsigned *Subtype) {713StringRef CPU;714715switch (Family) {716case 3:717CPU = "i386";718break;719case 4:720CPU = "i486";721break;722case 5:723if (testFeature(X86::FEATURE_MMX)) {724CPU = "pentium-mmx";725break;726}727CPU = "pentium";728break;729case 6:730switch (Model) {731case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile732// processor, Intel Core 2 Quad processor, Intel Core 2 Quad733// mobile processor, Intel Core 2 Extreme processor, Intel734// Pentium Dual-Core processor, Intel Xeon processor, model735// 0Fh. All processors are manufactured using the 65 nm process.736case 0x16: // Intel Celeron processor model 16h. All processors are737// manufactured using the 65 nm process738CPU = "core2";739*Type = X86::INTEL_CORE2;740break;741case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model742// 17h. All processors are manufactured using the 45 nm process.743//744// 45nm: Penryn , Wolfdale, Yorkfield (XE)745case 0x1d: // Intel Xeon processor MP. All processors are manufactured using746// the 45 nm process.747CPU = "penryn";748*Type = X86::INTEL_CORE2;749break;750case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All751// processors are manufactured using the 45 nm process.752case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.753// As found in a Summer 2010 model iMac.754case 0x1f:755case 0x2e: // Nehalem EX756CPU = "nehalem";757*Type = X86::INTEL_COREI7;758*Subtype = X86::INTEL_COREI7_NEHALEM;759break;760case 0x25: // Intel Core i7, laptop version.761case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All762// processors are manufactured using the 32 nm process.763case 0x2f: // Westmere EX764CPU = "westmere";765*Type = X86::INTEL_COREI7;766*Subtype = X86::INTEL_COREI7_WESTMERE;767break;768case 0x2a: // Intel Core i7 processor. All processors are manufactured769// using the 32 nm process.770case 0x2d:771CPU = "sandybridge";772*Type = X86::INTEL_COREI7;773*Subtype = X86::INTEL_COREI7_SANDYBRIDGE;774break;775case 0x3a:776case 0x3e: // Ivy Bridge EP777CPU = "ivybridge";778*Type = X86::INTEL_COREI7;779*Subtype = X86::INTEL_COREI7_IVYBRIDGE;780break;781782// Haswell:783case 0x3c:784case 0x3f:785case 0x45:786case 0x46:787CPU = "haswell";788*Type = X86::INTEL_COREI7;789*Subtype = X86::INTEL_COREI7_HASWELL;790break;791792// Broadwell:793case 0x3d:794case 0x47:795case 0x4f:796case 0x56:797CPU = "broadwell";798*Type = X86::INTEL_COREI7;799*Subtype = X86::INTEL_COREI7_BROADWELL;800break;801802// Skylake:803case 0x4e: // Skylake mobile804case 0x5e: // Skylake desktop805case 0x8e: // Kaby Lake mobile806case 0x9e: // Kaby Lake desktop807case 0xa5: // Comet Lake-H/S808case 0xa6: // Comet Lake-U809CPU = "skylake";810*Type = X86::INTEL_COREI7;811*Subtype = X86::INTEL_COREI7_SKYLAKE;812break;813814// Rocketlake:815case 0xa7:816CPU = "rocketlake";817*Type = X86::INTEL_COREI7;818*Subtype = X86::INTEL_COREI7_ROCKETLAKE;819break;820821// Skylake Xeon:822case 0x55:823*Type = X86::INTEL_COREI7;824if (testFeature(X86::FEATURE_AVX512BF16)) {825CPU = "cooperlake";826*Subtype = X86::INTEL_COREI7_COOPERLAKE;827} else if (testFeature(X86::FEATURE_AVX512VNNI)) {828CPU = "cascadelake";829*Subtype = X86::INTEL_COREI7_CASCADELAKE;830} else {831CPU = "skylake-avx512";832*Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;833}834break;835836// Cannonlake:837case 0x66:838CPU = "cannonlake";839*Type = X86::INTEL_COREI7;840*Subtype = X86::INTEL_COREI7_CANNONLAKE;841break;842843// Icelake:844case 0x7d:845case 0x7e:846CPU = "icelake-client";847*Type = X86::INTEL_COREI7;848*Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;849break;850851// Tigerlake:852case 0x8c:853case 0x8d:854CPU = "tigerlake";855*Type = X86::INTEL_COREI7;856*Subtype = X86::INTEL_COREI7_TIGERLAKE;857break;858859// Alderlake:860case 0x97:861case 0x9a:862// Gracemont863case 0xbe:864// Raptorlake:865case 0xb7:866case 0xba:867case 0xbf:868// Meteorlake:869case 0xaa:870case 0xac:871CPU = "alderlake";872*Type = X86::INTEL_COREI7;873*Subtype = X86::INTEL_COREI7_ALDERLAKE;874break;875876// Arrowlake:877case 0xc5:878CPU = "arrowlake";879*Type = X86::INTEL_COREI7;880*Subtype = X86::INTEL_COREI7_ARROWLAKE;881break;882883// Arrowlake S:884case 0xc6:885// Lunarlake:886case 0xbd:887CPU = "arrowlake-s";888*Type = X86::INTEL_COREI7;889*Subtype = X86::INTEL_COREI7_ARROWLAKE_S;890break;891892// Pantherlake:893case 0xcc:894CPU = "pantherlake";895*Type = X86::INTEL_COREI7;896*Subtype = X86::INTEL_COREI7_PANTHERLAKE;897break;898899// Graniterapids:900case 0xad:901CPU = "graniterapids";902*Type = X86::INTEL_COREI7;903*Subtype = X86::INTEL_COREI7_GRANITERAPIDS;904break;905906// Granite Rapids D:907case 0xae:908CPU = "graniterapids-d";909*Type = X86::INTEL_COREI7;910*Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;911break;912913// Icelake Xeon:914case 0x6a:915case 0x6c:916CPU = "icelake-server";917*Type = X86::INTEL_COREI7;918*Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;919break;920921// Emerald Rapids:922case 0xcf:923// Sapphire Rapids:924case 0x8f:925CPU = "sapphirerapids";926*Type = X86::INTEL_COREI7;927*Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;928break;929930case 0x1c: // Most 45 nm Intel Atom processors931case 0x26: // 45 nm Atom Lincroft932case 0x27: // 32 nm Atom Medfield933case 0x35: // 32 nm Atom Midview934case 0x36: // 32 nm Atom Midview935CPU = "bonnell";936*Type = X86::INTEL_BONNELL;937break;938939// Atom Silvermont codes from the Intel software optimization guide.940case 0x37:941case 0x4a:942case 0x4d:943case 0x5a:944case 0x5d:945case 0x4c: // really airmont946CPU = "silvermont";947*Type = X86::INTEL_SILVERMONT;948break;949// Goldmont:950case 0x5c: // Apollo Lake951case 0x5f: // Denverton952CPU = "goldmont";953*Type = X86::INTEL_GOLDMONT;954break;955case 0x7a:956CPU = "goldmont-plus";957*Type = X86::INTEL_GOLDMONT_PLUS;958break;959case 0x86:960case 0x8a: // Lakefield961case 0x96: // Elkhart Lake962case 0x9c: // Jasper Lake963CPU = "tremont";964*Type = X86::INTEL_TREMONT;965break;966967// Sierraforest:968case 0xaf:969CPU = "sierraforest";970*Type = X86::INTEL_SIERRAFOREST;971break;972973// Grandridge:974case 0xb6:975CPU = "grandridge";976*Type = X86::INTEL_GRANDRIDGE;977break;978979// Clearwaterforest:980case 0xdd:981CPU = "clearwaterforest";982*Type = X86::INTEL_CLEARWATERFOREST;983break;984985// Xeon Phi (Knights Landing + Knights Mill):986case 0x57:987CPU = "knl";988*Type = X86::INTEL_KNL;989break;990case 0x85:991CPU = "knm";992*Type = X86::INTEL_KNM;993break;994995default: // Unknown family 6 CPU, try to guess.996// Don't both with Type/Subtype here, they aren't used by the caller.997// They're used above to keep the code in sync with compiler-rt.998// TODO detect tigerlake host from model999if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {1000CPU = "tigerlake";1001} else if (testFeature(X86::FEATURE_AVX512VBMI2)) {1002CPU = "icelake-client";1003} else if (testFeature(X86::FEATURE_AVX512VBMI)) {1004CPU = "cannonlake";1005} else if (testFeature(X86::FEATURE_AVX512BF16)) {1006CPU = "cooperlake";1007} else if (testFeature(X86::FEATURE_AVX512VNNI)) {1008CPU = "cascadelake";1009} else if (testFeature(X86::FEATURE_AVX512VL)) {1010CPU = "skylake-avx512";1011} else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {1012if (testFeature(X86::FEATURE_SHA))1013CPU = "goldmont";1014else1015CPU = "skylake";1016} else if (testFeature(X86::FEATURE_ADX)) {1017CPU = "broadwell";1018} else if (testFeature(X86::FEATURE_AVX2)) {1019CPU = "haswell";1020} else if (testFeature(X86::FEATURE_AVX)) {1021CPU = "sandybridge";1022} else if (testFeature(X86::FEATURE_SSE4_2)) {1023if (testFeature(X86::FEATURE_MOVBE))1024CPU = "silvermont";1025else1026CPU = "nehalem";1027} else if (testFeature(X86::FEATURE_SSE4_1)) {1028CPU = "penryn";1029} else if (testFeature(X86::FEATURE_SSSE3)) {1030if (testFeature(X86::FEATURE_MOVBE))1031CPU = "bonnell";1032else1033CPU = "core2";1034} else if (testFeature(X86::FEATURE_64BIT)) {1035CPU = "core2";1036} else if (testFeature(X86::FEATURE_SSE3)) {1037CPU = "yonah";1038} else if (testFeature(X86::FEATURE_SSE2)) {1039CPU = "pentium-m";1040} else if (testFeature(X86::FEATURE_SSE)) {1041CPU = "pentium3";1042} else if (testFeature(X86::FEATURE_MMX)) {1043CPU = "pentium2";1044} else {1045CPU = "pentiumpro";1046}1047break;1048}1049break;1050case 15: {1051if (testFeature(X86::FEATURE_64BIT)) {1052CPU = "nocona";1053break;1054}1055if (testFeature(X86::FEATURE_SSE3)) {1056CPU = "prescott";1057break;1058}1059CPU = "pentium4";1060break;1061}1062default:1063break; // Unknown.1064}10651066return CPU;1067}10681069static const char *getAMDProcessorTypeAndSubtype(unsigned Family,1070unsigned Model,1071const unsigned *Features,1072unsigned *Type,1073unsigned *Subtype) {1074const char *CPU = 0;10751076switch (Family) {1077case 4:1078CPU = "i486";1079break;1080case 5:1081CPU = "pentium";1082switch (Model) {1083case 6:1084case 7:1085CPU = "k6";1086break;1087case 8:1088CPU = "k6-2";1089break;1090case 9:1091case 13:1092CPU = "k6-3";1093break;1094case 10:1095CPU = "geode";1096break;1097}1098break;1099case 6:1100if (testFeature(X86::FEATURE_SSE)) {1101CPU = "athlon-xp";1102break;1103}1104CPU = "athlon";1105break;1106case 15:1107if (testFeature(X86::FEATURE_SSE3)) {1108CPU = "k8-sse3";1109break;1110}1111CPU = "k8";1112break;1113case 16:1114CPU = "amdfam10";1115*Type = X86::AMDFAM10H; // "amdfam10"1116switch (Model) {1117case 2:1118*Subtype = X86::AMDFAM10H_BARCELONA;1119break;1120case 4:1121*Subtype = X86::AMDFAM10H_SHANGHAI;1122break;1123case 8:1124*Subtype = X86::AMDFAM10H_ISTANBUL;1125break;1126}1127break;1128case 20:1129CPU = "btver1";1130*Type = X86::AMD_BTVER1;1131break;1132case 21:1133CPU = "bdver1";1134*Type = X86::AMDFAM15H;1135if (Model >= 0x60 && Model <= 0x7f) {1136CPU = "bdver4";1137*Subtype = X86::AMDFAM15H_BDVER4;1138break; // 60h-7Fh: Excavator1139}1140if (Model >= 0x30 && Model <= 0x3f) {1141CPU = "bdver3";1142*Subtype = X86::AMDFAM15H_BDVER3;1143break; // 30h-3Fh: Steamroller1144}1145if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {1146CPU = "bdver2";1147*Subtype = X86::AMDFAM15H_BDVER2;1148break; // 02h, 10h-1Fh: Piledriver1149}1150if (Model <= 0x0f) {1151*Subtype = X86::AMDFAM15H_BDVER1;1152break; // 00h-0Fh: Bulldozer1153}1154break;1155case 22:1156CPU = "btver2";1157*Type = X86::AMD_BTVER2;1158break;1159case 23:1160CPU = "znver1";1161*Type = X86::AMDFAM17H;1162if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||1163(Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) ||1164(Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) ||1165(Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) ||1166(Model >= 0xa0 && Model <= 0xaf)) {1167// Family 17h Models 30h-3Fh (Starship) Zen 21168// Family 17h Models 47h (Cardinal) Zen 21169// Family 17h Models 60h-67h (Renoir) Zen 21170// Family 17h Models 68h-6Fh (Lucienne) Zen 21171// Family 17h Models 70h-7Fh (Matisse) Zen 21172// Family 17h Models 84h-87h (ProjectX) Zen 21173// Family 17h Models 90h-97h (VanGogh) Zen 21174// Family 17h Models 98h-9Fh (Mero) Zen 21175// Family 17h Models A0h-AFh (Mendocino) Zen 21176CPU = "znver2";1177*Subtype = X86::AMDFAM17H_ZNVER2;1178break;1179}1180if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) {1181// Family 17h Models 10h-1Fh (Raven1) Zen1182// Family 17h Models 10h-1Fh (Picasso) Zen+1183// Family 17h Models 20h-2Fh (Raven2 x86) Zen1184*Subtype = X86::AMDFAM17H_ZNVER1;1185break;1186}1187break;1188case 25:1189CPU = "znver3";1190*Type = X86::AMDFAM19H;1191if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||1192(Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||1193(Model >= 0x50 && Model <= 0x5f)) {1194// Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 31195// Family 19h Models 20h-2Fh (Vermeer) Zen 31196// Family 19h Models 30h-3Fh (Badami) Zen 31197// Family 19h Models 40h-4Fh (Rembrandt) Zen 3+1198// Family 19h Models 50h-5Fh (Cezanne) Zen 31199*Subtype = X86::AMDFAM19H_ZNVER3;1200break;1201}1202if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) ||1203(Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) ||1204(Model >= 0xa0 && Model <= 0xaf)) {1205// Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 41206// Family 19h Models 60h-6Fh (Raphael) Zen 41207// Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 41208// Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 41209// Family 19h Models A0h-AFh (Stones-Dense) Zen 41210CPU = "znver4";1211*Subtype = X86::AMDFAM19H_ZNVER4;1212break; // "znver4"1213}1214break; // family 19h1215case 26:1216CPU = "znver5";1217*Type = X86::AMDFAM1AH;1218if (Model <= 0x77) {1219// Models 00h-0Fh (Breithorn).1220// Models 10h-1Fh (Breithorn-Dense).1221// Models 20h-2Fh (Strix 1).1222// Models 30h-37h (Strix 2).1223// Models 38h-3Fh (Strix 3).1224// Models 40h-4Fh (Granite Ridge).1225// Models 50h-5Fh (Weisshorn).1226// Models 60h-6Fh (Krackan1).1227// Models 70h-77h (Sarlak).1228CPU = "znver5";1229*Subtype = X86::AMDFAM1AH_ZNVER5;1230break; // "znver5"1231}1232break;12331234default:1235break; // Unknown AMD CPU.1236}12371238return CPU;1239}12401241#undef testFeature12421243static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,1244unsigned *Features) {1245unsigned EAX, EBX;12461247auto setFeature = [&](unsigned F) {1248Features[F / 32] |= 1U << (F % 32);1249};12501251if ((EDX >> 15) & 1)1252setFeature(X86::FEATURE_CMOV);1253if ((EDX >> 23) & 1)1254setFeature(X86::FEATURE_MMX);1255if ((EDX >> 25) & 1)1256setFeature(X86::FEATURE_SSE);1257if ((EDX >> 26) & 1)1258setFeature(X86::FEATURE_SSE2);12591260if ((ECX >> 0) & 1)1261setFeature(X86::FEATURE_SSE3);1262if ((ECX >> 1) & 1)1263setFeature(X86::FEATURE_PCLMUL);1264if ((ECX >> 9) & 1)1265setFeature(X86::FEATURE_SSSE3);1266if ((ECX >> 12) & 1)1267setFeature(X86::FEATURE_FMA);1268if ((ECX >> 19) & 1)1269setFeature(X86::FEATURE_SSE4_1);1270if ((ECX >> 20) & 1) {1271setFeature(X86::FEATURE_SSE4_2);1272setFeature(X86::FEATURE_CRC32);1273}1274if ((ECX >> 23) & 1)1275setFeature(X86::FEATURE_POPCNT);1276if ((ECX >> 25) & 1)1277setFeature(X86::FEATURE_AES);12781279if ((ECX >> 22) & 1)1280setFeature(X86::FEATURE_MOVBE);12811282// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV1283// indicates that the AVX registers will be saved and restored on context1284// switch, then we have full AVX support.1285const unsigned AVXBits = (1 << 27) | (1 << 28);1286bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&1287((EAX & 0x6) == 0x6);1288#if defined(__APPLE__)1289// Darwin lazily saves the AVX512 context on first use: trust that the OS will1290// save the AVX512 context if we use AVX512 instructions, even the bit is not1291// set right now.1292bool HasAVX512Save = true;1293#else1294// AVX512 requires additional context to be saved by the OS.1295bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);1296#endif12971298if (HasAVX)1299setFeature(X86::FEATURE_AVX);13001301bool HasLeaf7 =1302MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);13031304if (HasLeaf7 && ((EBX >> 3) & 1))1305setFeature(X86::FEATURE_BMI);1306if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)1307setFeature(X86::FEATURE_AVX2);1308if (HasLeaf7 && ((EBX >> 8) & 1))1309setFeature(X86::FEATURE_BMI2);1310if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) {1311setFeature(X86::FEATURE_AVX512F);1312setFeature(X86::FEATURE_EVEX512);1313}1314if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)1315setFeature(X86::FEATURE_AVX512DQ);1316if (HasLeaf7 && ((EBX >> 19) & 1))1317setFeature(X86::FEATURE_ADX);1318if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)1319setFeature(X86::FEATURE_AVX512IFMA);1320if (HasLeaf7 && ((EBX >> 23) & 1))1321setFeature(X86::FEATURE_CLFLUSHOPT);1322if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)1323setFeature(X86::FEATURE_AVX512CD);1324if (HasLeaf7 && ((EBX >> 29) & 1))1325setFeature(X86::FEATURE_SHA);1326if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)1327setFeature(X86::FEATURE_AVX512BW);1328if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)1329setFeature(X86::FEATURE_AVX512VL);13301331if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)1332setFeature(X86::FEATURE_AVX512VBMI);1333if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)1334setFeature(X86::FEATURE_AVX512VBMI2);1335if (HasLeaf7 && ((ECX >> 8) & 1))1336setFeature(X86::FEATURE_GFNI);1337if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)1338setFeature(X86::FEATURE_VPCLMULQDQ);1339if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)1340setFeature(X86::FEATURE_AVX512VNNI);1341if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)1342setFeature(X86::FEATURE_AVX512BITALG);1343if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)1344setFeature(X86::FEATURE_AVX512VPOPCNTDQ);13451346if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)1347setFeature(X86::FEATURE_AVX5124VNNIW);1348if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)1349setFeature(X86::FEATURE_AVX5124FMAPS);1350if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)1351setFeature(X86::FEATURE_AVX512VP2INTERSECT);13521353// EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't1354// return all 0s for invalid subleaves so check the limit.1355bool HasLeaf7Subleaf1 =1356HasLeaf7 && EAX >= 1 &&1357!getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);1358if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)1359setFeature(X86::FEATURE_AVX512BF16);13601361unsigned MaxExtLevel;1362getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);13631364bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&1365!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);1366if (HasExtLeaf1 && ((ECX >> 6) & 1))1367setFeature(X86::FEATURE_SSE4_A);1368if (HasExtLeaf1 && ((ECX >> 11) & 1))1369setFeature(X86::FEATURE_XOP);1370if (HasExtLeaf1 && ((ECX >> 16) & 1))1371setFeature(X86::FEATURE_FMA4);13721373if (HasExtLeaf1 && ((EDX >> 29) & 1))1374setFeature(X86::FEATURE_64BIT);1375}13761377StringRef sys::getHostCPUName() {1378unsigned MaxLeaf = 0;1379const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);1380if (Vendor == VendorSignatures::UNKNOWN)1381return "generic";13821383unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;1384getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);13851386unsigned Family = 0, Model = 0;1387unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};1388detectX86FamilyModel(EAX, &Family, &Model);1389getAvailableFeatures(ECX, EDX, MaxLeaf, Features);13901391// These aren't consumed in this file, but we try to keep some source code the1392// same or similar to compiler-rt.1393unsigned Type = 0;1394unsigned Subtype = 0;13951396StringRef CPU;13971398if (Vendor == VendorSignatures::GENUINE_INTEL) {1399CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,1400&Subtype);1401} else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {1402CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,1403&Subtype);1404}14051406if (!CPU.empty())1407return CPU;14081409return "generic";1410}14111412#elif defined(__APPLE__) && defined(__powerpc__)1413StringRef sys::getHostCPUName() {1414host_basic_info_data_t hostInfo;1415mach_msg_type_number_t infoCount;14161417infoCount = HOST_BASIC_INFO_COUNT;1418mach_port_t hostPort = mach_host_self();1419host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,1420&infoCount);1421mach_port_deallocate(mach_task_self(), hostPort);14221423if (hostInfo.cpu_type != CPU_TYPE_POWERPC)1424return "generic";14251426switch (hostInfo.cpu_subtype) {1427case CPU_SUBTYPE_POWERPC_601:1428return "601";1429case CPU_SUBTYPE_POWERPC_602:1430return "602";1431case CPU_SUBTYPE_POWERPC_603:1432return "603";1433case CPU_SUBTYPE_POWERPC_603e:1434return "603e";1435case CPU_SUBTYPE_POWERPC_603ev:1436return "603ev";1437case CPU_SUBTYPE_POWERPC_604:1438return "604";1439case CPU_SUBTYPE_POWERPC_604e:1440return "604e";1441case CPU_SUBTYPE_POWERPC_620:1442return "620";1443case CPU_SUBTYPE_POWERPC_750:1444return "750";1445case CPU_SUBTYPE_POWERPC_7400:1446return "7400";1447case CPU_SUBTYPE_POWERPC_7450:1448return "7450";1449case CPU_SUBTYPE_POWERPC_970:1450return "970";1451default:;1452}14531454return "generic";1455}1456#elif defined(__linux__) && defined(__powerpc__)1457StringRef sys::getHostCPUName() {1458std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1459StringRef Content = P ? P->getBuffer() : "";1460return detail::getHostCPUNameForPowerPC(Content);1461}1462#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))1463StringRef sys::getHostCPUName() {1464std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1465StringRef Content = P ? P->getBuffer() : "";1466return detail::getHostCPUNameForARM(Content);1467}1468#elif defined(__linux__) && defined(__s390x__)1469StringRef sys::getHostCPUName() {1470std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1471StringRef Content = P ? P->getBuffer() : "";1472return detail::getHostCPUNameForS390x(Content);1473}1474#elif defined(__MVS__)1475StringRef sys::getHostCPUName() {1476// Get pointer to Communications Vector Table (CVT).1477// The pointer is located at offset 16 of the Prefixed Save Area (PSA).1478// It is stored as 31 bit pointer and will be zero-extended to 64 bit.1479int *StartToCVTOffset = reinterpret_cast<int *>(0x10);1480// Since its stored as a 31-bit pointer, get the 4 bytes from the start1481// of address.1482int ReadValue = *StartToCVTOffset;1483// Explicitly clear the high order bit.1484ReadValue = (ReadValue & 0x7FFFFFFF);1485char *CVT = reinterpret_cast<char *>(ReadValue);1486// The model number is located in the CVT prefix at offset -6 and stored as1487// signless packed decimal.1488uint16_t Id = *(uint16_t *)&CVT[-6];1489// Convert number to integer.1490Id = decodePackedBCD<uint16_t>(Id, false);1491// Check for vector support. It's stored in field CVTFLAG5 (offset 244),1492// bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector1493// extension can only be used if bit CVTVEF is on.1494bool HaveVectorSupport = CVT[244] & 0x80;1495return getCPUNameFromS390Model(Id, HaveVectorSupport);1496}1497#elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))1498#define CPUFAMILY_ARM_SWIFT 0x1e2d63811499#define CPUFAMILY_ARM_CYCLONE 0x37a096421500#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e1501#define CPUFAMILY_ARM_TWISTER 0x92fb37c81502#define CPUFAMILY_ARM_HURRICANE 0x67ceee931503#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef61504#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f1505#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d21506#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb31507#define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d1508#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea15091510StringRef sys::getHostCPUName() {1511uint32_t Family;1512size_t Length = sizeof(Family);1513sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);15141515switch (Family) {1516case CPUFAMILY_ARM_SWIFT:1517return "swift";1518case CPUFAMILY_ARM_CYCLONE:1519return "apple-a7";1520case CPUFAMILY_ARM_TYPHOON:1521return "apple-a8";1522case CPUFAMILY_ARM_TWISTER:1523return "apple-a9";1524case CPUFAMILY_ARM_HURRICANE:1525return "apple-a10";1526case CPUFAMILY_ARM_MONSOON_MISTRAL:1527return "apple-a11";1528case CPUFAMILY_ARM_VORTEX_TEMPEST:1529return "apple-a12";1530case CPUFAMILY_ARM_LIGHTNING_THUNDER:1531return "apple-a13";1532case CPUFAMILY_ARM_FIRESTORM_ICESTORM:1533return "apple-m1";1534case CPUFAMILY_ARM_BLIZZARD_AVALANCHE:1535return "apple-m2";1536case CPUFAMILY_ARM_EVEREST_SAWTOOTH:1537return "apple-m3";1538default:1539// Default to the newest CPU we know about.1540return "apple-m3";1541}1542}1543#elif defined(_AIX)1544StringRef sys::getHostCPUName() {1545switch (_system_configuration.implementation) {1546case POWER_4:1547if (_system_configuration.version == PV_4_3)1548return "970";1549return "pwr4";1550case POWER_5:1551if (_system_configuration.version == PV_5)1552return "pwr5";1553return "pwr5x";1554case POWER_6:1555if (_system_configuration.version == PV_6_Compat)1556return "pwr6";1557return "pwr6x";1558case POWER_7:1559return "pwr7";1560case POWER_8:1561return "pwr8";1562case POWER_9:1563return "pwr9";1564// TODO: simplify this once the macro is available in all OS levels.1565#ifdef POWER_101566case POWER_10:1567#else1568case 0x40000:1569#endif1570return "pwr10";1571#ifdef POWER_111572case POWER_11:1573#else1574case 0x80000:1575#endif1576return "pwr11";1577default:1578return "generic";1579}1580}1581#elif defined(__loongarch__)1582StringRef sys::getHostCPUName() {1583// Use processor id to detect cpu name.1584uint32_t processor_id;1585__asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));1586// Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h.1587switch (processor_id & 0xf000) {1588case 0xc000: // Loongson 64bit, 4-issue1589return "la464";1590case 0xd000: // Loongson 64bit, 6-issue1591return "la664";1592// TODO: Others.1593default:1594break;1595}1596return "generic";1597}1598#elif defined(__riscv)1599StringRef sys::getHostCPUName() {1600#if defined(__linux__)1601std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1602StringRef Content = P ? P->getBuffer() : "";1603StringRef Name = detail::getHostCPUNameForRISCV(Content);1604if (!Name.empty())1605return Name;1606#endif1607#if __riscv_xlen == 641608return "generic-rv64";1609#elif __riscv_xlen == 321610return "generic-rv32";1611#else1612#error "Unhandled value of __riscv_xlen"1613#endif1614}1615#elif defined(__sparc__)1616#if defined(__linux__)1617StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {1618SmallVector<StringRef> Lines;1619ProcCpuinfoContent.split(Lines, "\n");16201621// Look for cpu line to determine cpu name1622StringRef Cpu;1623for (unsigned I = 0, E = Lines.size(); I != E; ++I) {1624if (Lines[I].starts_with("cpu")) {1625Cpu = Lines[I].substr(5).ltrim("\t :");1626break;1627}1628}16291630return StringSwitch<const char *>(Cpu)1631.StartsWith("SuperSparc", "supersparc")1632.StartsWith("HyperSparc", "hypersparc")1633.StartsWith("SpitFire", "ultrasparc")1634.StartsWith("BlackBird", "ultrasparc")1635.StartsWith("Sabre", " ultrasparc")1636.StartsWith("Hummingbird", "ultrasparc")1637.StartsWith("Cheetah", "ultrasparc3")1638.StartsWith("Jalapeno", "ultrasparc3")1639.StartsWith("Jaguar", "ultrasparc3")1640.StartsWith("Panther", "ultrasparc3")1641.StartsWith("Serrano", "ultrasparc3")1642.StartsWith("UltraSparc T1", "niagara")1643.StartsWith("UltraSparc T2", "niagara2")1644.StartsWith("UltraSparc T3", "niagara3")1645.StartsWith("UltraSparc T4", "niagara4")1646.StartsWith("UltraSparc T5", "niagara4")1647.StartsWith("LEON", "leon3")1648// niagara7/m8 not supported by LLVM yet.1649.StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)1650.StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)1651.StartsWith("SPARC-M8", "niagara4" /* "m8" */)1652.Default("generic");1653}1654#endif16551656StringRef sys::getHostCPUName() {1657#if defined(__linux__)1658std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1659StringRef Content = P ? P->getBuffer() : "";1660return detail::getHostCPUNameForSPARC(Content);1661#elif defined(__sun__) && defined(__svr4__)1662char *buf = NULL;1663kstat_ctl_t *kc;1664kstat_t *ksp;1665kstat_named_t *brand = NULL;16661667kc = kstat_open();1668if (kc != NULL) {1669ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);1670if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&1671ksp->ks_type == KSTAT_TYPE_NAMED)1672brand =1673(kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));1674if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)1675buf = KSTAT_NAMED_STR_PTR(brand);1676}1677kstat_close(kc);16781679return StringSwitch<const char *>(buf)1680.Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I1681.Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I1682.Case("TMS390Z55",1683"supersparc") // Texas Instruments SuperSPARC I with SuperCache1684.Case("MB86904", "supersparc") // Fujitsu microSPARC II1685.Case("MB86907", "supersparc") // Fujitsu TurboSPARC1686.Case("RT623", "hypersparc") // Ross hyperSPARC1687.Case("RT625", "hypersparc")1688.Case("RT626", "hypersparc")1689.Case("UltraSPARC-I", "ultrasparc")1690.Case("UltraSPARC-II", "ultrasparc")1691.Case("UltraSPARC-IIe", "ultrasparc")1692.Case("UltraSPARC-IIi", "ultrasparc")1693.Case("SPARC64-III", "ultrasparc")1694.Case("SPARC64-IV", "ultrasparc")1695.Case("UltraSPARC-III", "ultrasparc3")1696.Case("UltraSPARC-III+", "ultrasparc3")1697.Case("UltraSPARC-IIIi", "ultrasparc3")1698.Case("UltraSPARC-IIIi+", "ultrasparc3")1699.Case("UltraSPARC-IV", "ultrasparc3")1700.Case("UltraSPARC-IV+", "ultrasparc3")1701.Case("SPARC64-V", "ultrasparc3")1702.Case("SPARC64-VI", "ultrasparc3")1703.Case("SPARC64-VII", "ultrasparc3")1704.Case("UltraSPARC-T1", "niagara")1705.Case("UltraSPARC-T2", "niagara2")1706.Case("UltraSPARC-T2", "niagara2")1707.Case("UltraSPARC-T2+", "niagara2")1708.Case("SPARC-T3", "niagara3")1709.Case("SPARC-T4", "niagara4")1710.Case("SPARC-T5", "niagara4")1711// niagara7/m8 not supported by LLVM yet.1712.Case("SPARC-M7", "niagara4" /* "niagara7" */)1713.Case("SPARC-S7", "niagara4" /* "niagara7" */)1714.Case("SPARC-M8", "niagara4" /* "m8" */)1715.Default("generic");1716#else1717return "generic";1718#endif1719}1720#else1721StringRef sys::getHostCPUName() { return "generic"; }1722namespace llvm {1723namespace sys {1724namespace detail {1725namespace x86 {17261727VendorSignatures getVendorSignature(unsigned *MaxLeaf) {1728return VendorSignatures::UNKNOWN;1729}17301731} // namespace x861732} // namespace detail1733} // namespace sys1734} // namespace llvm1735#endif17361737#if defined(__i386__) || defined(_M_IX86) || \1738defined(__x86_64__) || defined(_M_X64)1739const StringMap<bool> sys::getHostCPUFeatures() {1740unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;1741unsigned MaxLevel;1742StringMap<bool> Features;17431744if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)1745return Features;17461747getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);17481749Features["cx8"] = (EDX >> 8) & 1;1750Features["cmov"] = (EDX >> 15) & 1;1751Features["mmx"] = (EDX >> 23) & 1;1752Features["fxsr"] = (EDX >> 24) & 1;1753Features["sse"] = (EDX >> 25) & 1;1754Features["sse2"] = (EDX >> 26) & 1;17551756Features["sse3"] = (ECX >> 0) & 1;1757Features["pclmul"] = (ECX >> 1) & 1;1758Features["ssse3"] = (ECX >> 9) & 1;1759Features["cx16"] = (ECX >> 13) & 1;1760Features["sse4.1"] = (ECX >> 19) & 1;1761Features["sse4.2"] = (ECX >> 20) & 1;1762Features["crc32"] = Features["sse4.2"];1763Features["movbe"] = (ECX >> 22) & 1;1764Features["popcnt"] = (ECX >> 23) & 1;1765Features["aes"] = (ECX >> 25) & 1;1766Features["rdrnd"] = (ECX >> 30) & 1;17671768// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV1769// indicates that the AVX registers will be saved and restored on context1770// switch, then we have full AVX support.1771bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);1772bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);1773#if defined(__APPLE__)1774// Darwin lazily saves the AVX512 context on first use: trust that the OS will1775// save the AVX512 context if we use AVX512 instructions, even the bit is not1776// set right now.1777bool HasAVX512Save = true;1778#else1779// AVX512 requires additional context to be saved by the OS.1780bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);1781#endif1782// AMX requires additional context to be saved by the OS.1783const unsigned AMXBits = (1 << 17) | (1 << 18);1784bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);17851786Features["avx"] = HasAVXSave;1787Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;1788// Only enable XSAVE if OS has enabled support for saving YMM state.1789Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;1790Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave;17911792unsigned MaxExtLevel;1793getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);17941795bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&1796!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);1797Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1);1798Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);1799Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);1800Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);1801Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;1802Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1);1803Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;1804Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);1805Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);18061807Features["64bit"] = HasExtLeaf1 && ((EDX >> 29) & 1);18081809// Miscellaneous memory related features, detected by1810// using the 0x80000008 leaf of the CPUID instruction1811bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&1812!getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);1813Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1);1814Features["rdpru"] = HasExtLeaf8 && ((EBX >> 4) & 1);1815Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);18161817bool HasLeaf7 =1818MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);18191820Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);1821Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);1822Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);1823// AVX2 is only supported if we have the OS save support from AVX.1824Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave;1825Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);1826Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);1827Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);1828// AVX512 is only supported if the OS supports the context save for it.1829Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;1830if (Features["avx512f"])1831Features["evex512"] = true;1832Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;1833Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);1834Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);1835Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;1836Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);1837Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);1838Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;1839Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);1840Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;1841Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;18421843Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;1844Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);1845Features["waitpkg"] = HasLeaf7 && ((ECX >> 5) & 1);1846Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save;1847Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1);1848Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1);1849Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave;1850Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;1851Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;1852Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;1853Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;1854Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1);1855Features["kl"] = HasLeaf7 && ((ECX >> 23) & 1); // key locker1856Features["cldemote"] = HasLeaf7 && ((ECX >> 25) & 1);1857Features["movdiri"] = HasLeaf7 && ((ECX >> 27) & 1);1858Features["movdir64b"] = HasLeaf7 && ((ECX >> 28) & 1);1859Features["enqcmd"] = HasLeaf7 && ((ECX >> 29) & 1);18601861Features["uintr"] = HasLeaf7 && ((EDX >> 5) & 1);1862Features["avx512vp2intersect"] =1863HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;1864Features["serialize"] = HasLeaf7 && ((EDX >> 14) & 1);1865Features["tsxldtrk"] = HasLeaf7 && ((EDX >> 16) & 1);1866// There are two CPUID leafs which information associated with the pconfig1867// instruction:1868// EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th1869// bit of EDX), while the EAX=0x1b leaf returns information on the1870// availability of specific pconfig leafs.1871// The target feature here only refers to the the first of these two.1872// Users might need to check for the availability of specific pconfig1873// leaves using cpuid, since that information is ignored while1874// detecting features using the "-march=native" flag.1875// For more info, see X86 ISA docs.1876Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);1877Features["amx-bf16"] = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;1878Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;1879Features["amx-tile"] = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;1880Features["amx-int8"] = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;1881// EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't1882// return all 0s for invalid subleaves so check the limit.1883bool HasLeaf7Subleaf1 =1884HasLeaf7 && EAX >= 1 &&1885!getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);1886Features["sha512"] = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);1887Features["sm3"] = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);1888Features["sm4"] = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);1889Features["raoint"] = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);1890Features["avxvnni"] = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;1891Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;1892Features["amx-fp16"] = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;1893Features["cmpccxadd"] = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);1894Features["hreset"] = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);1895Features["avxifma"] = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;1896Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;1897Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;1898Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;1899Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;1900Features["prefetchi"] = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);1901Features["usermsr"] = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);1902Features["avx10.1-256"] = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);1903bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);1904Features["egpr"] = HasAPXF;1905Features["push2pop2"] = HasAPXF;1906Features["ppx"] = HasAPXF;1907Features["ndd"] = HasAPXF;1908Features["ccmp"] = HasAPXF;1909Features["cf"] = HasAPXF;19101911bool HasLeafD = MaxLevel >= 0xd &&1912!getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);19131914// Only enable XSAVE if OS has enabled support for saving YMM state.1915Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;1916Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;1917Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;19181919bool HasLeaf14 = MaxLevel >= 0x14 &&1920!getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);19211922Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);19231924bool HasLeaf19 =1925MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);1926Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);19271928bool HasLeaf24 =1929MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);1930Features["avx10.1-512"] =1931Features["avx10.1-256"] && HasLeaf24 && ((EBX >> 18) & 1);19321933return Features;1934}1935#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))1936const StringMap<bool> sys::getHostCPUFeatures() {1937StringMap<bool> Features;1938std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1939if (!P)1940return Features;19411942SmallVector<StringRef, 32> Lines;1943P->getBuffer().split(Lines, "\n");19441945SmallVector<StringRef, 32> CPUFeatures;19461947// Look for the CPU features.1948for (unsigned I = 0, E = Lines.size(); I != E; ++I)1949if (Lines[I].starts_with("Features")) {1950Lines[I].split(CPUFeatures, ' ');1951break;1952}19531954#if defined(__aarch64__)1955// Keep track of which crypto features we have seen1956enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };1957uint32_t crypto = 0;1958#endif19591960for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {1961StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])1962#if defined(__aarch64__)1963.Case("asimd", "neon")1964.Case("fp", "fp-armv8")1965.Case("crc32", "crc")1966.Case("atomics", "lse")1967.Case("sve", "sve")1968.Case("sve2", "sve2")1969#else1970.Case("half", "fp16")1971.Case("neon", "neon")1972.Case("vfpv3", "vfp3")1973.Case("vfpv3d16", "vfp3d16")1974.Case("vfpv4", "vfp4")1975.Case("idiva", "hwdiv-arm")1976.Case("idivt", "hwdiv")1977#endif1978.Default("");19791980#if defined(__aarch64__)1981// We need to check crypto separately since we need all of the crypto1982// extensions to enable the subtarget feature1983if (CPUFeatures[I] == "aes")1984crypto |= CAP_AES;1985else if (CPUFeatures[I] == "pmull")1986crypto |= CAP_PMULL;1987else if (CPUFeatures[I] == "sha1")1988crypto |= CAP_SHA1;1989else if (CPUFeatures[I] == "sha2")1990crypto |= CAP_SHA2;1991#endif19921993if (LLVMFeatureStr != "")1994Features[LLVMFeatureStr] = true;1995}19961997#if defined(__aarch64__)1998// If we have all crypto bits we can add the feature1999if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))2000Features["crypto"] = true;2001#endif20022003return Features;2004}2005#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))2006const StringMap<bool> sys::getHostCPUFeatures() {2007StringMap<bool> Features;20082009if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))2010Features["neon"] = true;2011if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))2012Features["crc"] = true;2013if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))2014Features["crypto"] = true;20152016return Features;2017}2018#elif defined(__linux__) && defined(__loongarch__)2019#include <sys/auxv.h>2020const StringMap<bool> sys::getHostCPUFeatures() {2021unsigned long hwcap = getauxval(AT_HWCAP);2022bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU2023uint32_t cpucfg2 = 0x2;2024__asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));20252026StringMap<bool> Features;20272028Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP2029Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP20302031Features["lsx"] = hwcap & (1UL << 4); // HWCAP_LOONGARCH_LSX2032Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX2033Features["lvz"] = hwcap & (1UL << 9); // HWCAP_LOONGARCH_LVZ20342035return Features;2036}2037#elif defined(__linux__) && defined(__riscv)2038// struct riscv_hwprobe2039struct RISCVHwProbe {2040int64_t Key;2041uint64_t Value;2042};2043const StringMap<bool> sys::getHostCPUFeatures() {2044RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0},2045{/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0}};2046int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,2047/*pair_count=*/std::size(Query), /*cpu_count=*/0,2048/*cpus=*/0, /*flags=*/0);2049if (Ret != 0)2050return {};20512052StringMap<bool> Features;2053uint64_t BaseMask = Query[0].Value;2054// Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set.2055if (BaseMask & 1) {2056Features["i"] = true;2057Features["m"] = true;2058Features["a"] = true;2059}20602061uint64_t ExtMask = Query[1].Value;2062Features["f"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD2063Features["d"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD2064Features["c"] = ExtMask & (1 << 1); // RISCV_HWPROBE_IMA_C2065Features["v"] = ExtMask & (1 << 2); // RISCV_HWPROBE_IMA_V2066Features["zba"] = ExtMask & (1 << 3); // RISCV_HWPROBE_EXT_ZBA2067Features["zbb"] = ExtMask & (1 << 4); // RISCV_HWPROBE_EXT_ZBB2068Features["zbs"] = ExtMask & (1 << 5); // RISCV_HWPROBE_EXT_ZBS2069Features["zicboz"] = ExtMask & (1 << 6); // RISCV_HWPROBE_EXT_ZICBOZ2070Features["zbc"] = ExtMask & (1 << 7); // RISCV_HWPROBE_EXT_ZBC2071Features["zbkb"] = ExtMask & (1 << 8); // RISCV_HWPROBE_EXT_ZBKB2072Features["zbkc"] = ExtMask & (1 << 9); // RISCV_HWPROBE_EXT_ZBKC2073Features["zbkx"] = ExtMask & (1 << 10); // RISCV_HWPROBE_EXT_ZBKX2074Features["zknd"] = ExtMask & (1 << 11); // RISCV_HWPROBE_EXT_ZKND2075Features["zkne"] = ExtMask & (1 << 12); // RISCV_HWPROBE_EXT_ZKNE2076Features["zknh"] = ExtMask & (1 << 13); // RISCV_HWPROBE_EXT_ZKNH2077Features["zksed"] = ExtMask & (1 << 14); // RISCV_HWPROBE_EXT_ZKSED2078Features["zksh"] = ExtMask & (1 << 15); // RISCV_HWPROBE_EXT_ZKSH2079Features["zkt"] = ExtMask & (1 << 16); // RISCV_HWPROBE_EXT_ZKT2080Features["zvbb"] = ExtMask & (1 << 17); // RISCV_HWPROBE_EXT_ZVBB2081Features["zvbc"] = ExtMask & (1 << 18); // RISCV_HWPROBE_EXT_ZVBC2082Features["zvkb"] = ExtMask & (1 << 19); // RISCV_HWPROBE_EXT_ZVKB2083Features["zvkg"] = ExtMask & (1 << 20); // RISCV_HWPROBE_EXT_ZVKG2084Features["zvkned"] = ExtMask & (1 << 21); // RISCV_HWPROBE_EXT_ZVKNED2085Features["zvknha"] = ExtMask & (1 << 22); // RISCV_HWPROBE_EXT_ZVKNHA2086Features["zvknhb"] = ExtMask & (1 << 23); // RISCV_HWPROBE_EXT_ZVKNHB2087Features["zvksed"] = ExtMask & (1 << 24); // RISCV_HWPROBE_EXT_ZVKSED2088Features["zvksh"] = ExtMask & (1 << 25); // RISCV_HWPROBE_EXT_ZVKSH2089Features["zvkt"] = ExtMask & (1 << 26); // RISCV_HWPROBE_EXT_ZVKT2090Features["zfh"] = ExtMask & (1 << 27); // RISCV_HWPROBE_EXT_ZFH2091Features["zfhmin"] = ExtMask & (1 << 28); // RISCV_HWPROBE_EXT_ZFHMIN2092Features["zihintntl"] = ExtMask & (1 << 29); // RISCV_HWPROBE_EXT_ZIHINTNTL2093Features["zvfh"] = ExtMask & (1 << 30); // RISCV_HWPROBE_EXT_ZVFH2094Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN2095Features["zfa"] = ExtMask & (1ULL << 32); // RISCV_HWPROBE_EXT_ZFA2096Features["ztso"] = ExtMask & (1ULL << 33); // RISCV_HWPROBE_EXT_ZTSO2097// TODO: Re-enable zacas when it is marked non-experimental again.2098// Features["zacas"] = ExtMask & (1ULL << 34); // RISCV_HWPROBE_EXT_ZACAS2099Features["zicond"] = ExtMask & (1ULL << 35); // RISCV_HWPROBE_EXT_ZICOND2100Features["zihintpause"] =2101ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE21022103// TODO: set unaligned-scalar-mem if RISCV_HWPROBE_KEY_MISALIGNED_PERF returns2104// RISCV_HWPROBE_MISALIGNED_FAST.21052106return Features;2107}2108#else2109const StringMap<bool> sys::getHostCPUFeatures() { return {}; }2110#endif21112112#if __APPLE__2113/// \returns the \p triple, but with the Host's arch spliced in.2114static Triple withHostArch(Triple T) {2115#if defined(__arm__)2116T.setArch(Triple::arm);2117T.setArchName("arm");2118#elif defined(__arm64e__)2119T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);2120T.setArchName("arm64e");2121#elif defined(__aarch64__)2122T.setArch(Triple::aarch64);2123T.setArchName("arm64");2124#elif defined(__x86_64h__)2125T.setArch(Triple::x86_64);2126T.setArchName("x86_64h");2127#elif defined(__x86_64__)2128T.setArch(Triple::x86_64);2129T.setArchName("x86_64");2130#elif defined(__i386__)2131T.setArch(Triple::x86);2132T.setArchName("i386");2133#elif defined(__powerpc__)2134T.setArch(Triple::ppc);2135T.setArchName("powerpc");2136#else2137# error "Unimplemented host arch fixup"2138#endif2139return T;2140}2141#endif21422143std::string sys::getProcessTriple() {2144std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);2145Triple PT(Triple::normalize(TargetTripleString));21462147#if __APPLE__2148/// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of2149/// the slices. This fixes that up.2150PT = withHostArch(PT);2151#endif21522153if (sizeof(void *) == 8 && PT.isArch32Bit())2154PT = PT.get64BitArchVariant();2155if (sizeof(void *) == 4 && PT.isArch64Bit())2156PT = PT.get32BitArchVariant();21572158return PT.str();2159}21602161void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {2162#if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO2163std::string CPU = std::string(sys::getHostCPUName());2164if (CPU == "generic")2165CPU = "(unknown)";2166OS << " Default target: " << sys::getDefaultTargetTriple() << '\n'2167<< " Host CPU: " << CPU << '\n';2168#endif2169}217021712172