brintos

brintos / llvm-project-archived public Read only

0
0
Text · 86.8 KiB · cb793d6 Raw
2539 lines · cpp
1//===-- Host.cpp - Implement OS Host Detection ------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements the operating system Host detection.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/TargetParser/Host.h"14#include "llvm/ADT/Bitfields.h"15#include "llvm/ADT/STLFunctionalExtras.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/StringExtras.h"18#include "llvm/ADT/StringMap.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/ADT/StringSwitch.h"21#include "llvm/Config/llvm-config.h"22#include "llvm/Support/MemoryBuffer.h"23#include "llvm/Support/raw_ostream.h"24#include "llvm/TargetParser/RISCVTargetParser.h"25#include "llvm/TargetParser/Triple.h"26#include "llvm/TargetParser/X86TargetParser.h"27#include <string.h>28 29// Include the platform-specific parts of this class.30#ifdef LLVM_ON_UNIX31#include "Unix/Host.inc"32#include <sched.h>33#endif34#ifdef _WIN3235#include "Windows/Host.inc"36#endif37#ifdef _MSC_VER38#include <intrin.h>39#endif40#ifdef __MVS__41#include "llvm/Support/BCD.h"42#endif43#if defined(__APPLE__)44#include <mach/host_info.h>45#include <mach/mach.h>46#include <mach/mach_host.h>47#include <mach/machine.h>48#include <sys/param.h>49#include <sys/sysctl.h>50#endif51#ifdef _AIX52#include <sys/systemcfg.h>53#endif54#if defined(__sun__) && defined(__svr4__)55#include <kstat.h>56#endif57#if defined(__GNUC__) || defined(__clang__)58#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)59#include <cpuid.h>60#endif61#endif62 63#define DEBUG_TYPE "host-detection"64 65//===----------------------------------------------------------------------===//66//67//  Implementations of the CPU detection routines68//69//===----------------------------------------------------------------------===//70 71using namespace llvm;72 73[[maybe_unused]] static std::unique_ptr<llvm::MemoryBuffer>74getProcCpuinfoContent() {75  const char *CPUInfoFile = "/proc/cpuinfo";76  if (const char *CpuinfoIntercept = std::getenv("LLVM_CPUINFO"))77    CPUInfoFile = CpuinfoIntercept;78  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =79      llvm::MemoryBuffer::getFileAsStream(CPUInfoFile);80 81  if (std::error_code EC = Text.getError()) {82    llvm::errs() << "Can't read " << CPUInfoFile << ": " << EC.message()83                 << "\n";84    return nullptr;85  }86  return std::move(*Text);87}88 89StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {90  // Access to the Processor Version Register (PVR) on PowerPC is privileged,91  // and so we must use an operating-system interface to determine the current92  // processor type. On Linux, this is exposed through the /proc/cpuinfo file.93  const char *generic = "generic";94 95  // The cpu line is second (after the 'processor: 0' line), so if this96  // buffer is too small then something has changed (or is wrong).97  StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();98  StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();99 100  StringRef::const_iterator CIP = CPUInfoStart;101 102  StringRef::const_iterator CPUStart = nullptr;103  size_t CPULen = 0;104 105  // We need to find the first line which starts with cpu, spaces, and a colon.106  // After the colon, there may be some additional spaces and then the cpu type.107  while (CIP < CPUInfoEnd && CPUStart == nullptr) {108    if (CIP < CPUInfoEnd && *CIP == '\n')109      ++CIP;110 111    if (CIP < CPUInfoEnd && *CIP == 'c') {112      ++CIP;113      if (CIP < CPUInfoEnd && *CIP == 'p') {114        ++CIP;115        if (CIP < CPUInfoEnd && *CIP == 'u') {116          ++CIP;117          while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))118            ++CIP;119 120          if (CIP < CPUInfoEnd && *CIP == ':') {121            ++CIP;122            while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))123              ++CIP;124 125            if (CIP < CPUInfoEnd) {126              CPUStart = CIP;127              while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&128                                          *CIP != ',' && *CIP != '\n'))129                ++CIP;130              CPULen = CIP - CPUStart;131            }132          }133        }134      }135    }136 137    if (CPUStart == nullptr)138      while (CIP < CPUInfoEnd && *CIP != '\n')139        ++CIP;140  }141 142  if (CPUStart == nullptr)143    return generic;144 145  return StringSwitch<const char *>(StringRef(CPUStart, CPULen))146      .Case("604e", "604e")147      .Case("604", "604")148      .Case("7400", "7400")149      .Case("7410", "7400")150      .Case("7447", "7400")151      .Case("7455", "7450")152      .Case("G4", "g4")153      .Case("POWER4", "970")154      .Case("PPC970FX", "970")155      .Case("PPC970MP", "970")156      .Case("G5", "g5")157      .Case("POWER5", "g5")158      .Case("A2", "a2")159      .Case("POWER6", "pwr6")160      .Case("POWER7", "pwr7")161      .Case("POWER8", "pwr8")162      .Case("POWER8E", "pwr8")163      .Case("POWER8NVL", "pwr8")164      .Case("POWER9", "pwr9")165      .Case("POWER10", "pwr10")166      .Case("POWER11", "pwr11")167      // FIXME: If we get a simulator or machine with the capabilities of168      // mcpu=future, we should revisit this and add the name reported by the169      // simulator/machine.170      .Default(generic);171}172 173StringRef174getHostCPUNameForARMFromComponents(StringRef Implementer, StringRef Hardware,175                                   StringRef Part, ArrayRef<StringRef> Parts,176                                   function_ref<unsigned()> GetVariant) {177 178  auto MatchBigLittle = [](auto const &Parts, StringRef Big, StringRef Little) {179    if (Parts.size() == 2)180      return (Parts[0] == Big && Parts[1] == Little) ||181             (Parts[1] == Big && Parts[0] == Little);182    return false;183  };184 185  if (Implementer == "0x41") { // ARM Ltd.186    // MSM8992/8994 may give cpu part for the core that the kernel is running on,187    // which is undeterministic and wrong. Always return cortex-a53 for these SoC.188    if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996"))189      return "cortex-a53";190 191    // Detect big.LITTLE systems.192    if (MatchBigLittle(Parts, "0xd85", "0xd87"))193      return "cortex-x925";194 195    // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The196    // values correspond to the "Part number" in the CP15/c0 register. The197    // contents are specified in the various processor manuals.198    // This corresponds to the Main ID Register in Technical Reference Manuals.199    // and is used in programs like sys-utils200    return StringSwitch<const char *>(Part)201        .Case("0x926", "arm926ej-s")202        .Case("0xb02", "mpcore")203        .Case("0xb36", "arm1136j-s")204        .Case("0xb56", "arm1156t2-s")205        .Case("0xb76", "arm1176jz-s")206        .Case("0xc05", "cortex-a5")207        .Case("0xc07", "cortex-a7")208        .Case("0xc08", "cortex-a8")209        .Case("0xc09", "cortex-a9")210        .Case("0xc0f", "cortex-a15")211        .Case("0xc0e", "cortex-a17")212        .Case("0xc20", "cortex-m0")213        .Case("0xc23", "cortex-m3")214        .Case("0xc24", "cortex-m4")215        .Case("0xc27", "cortex-m7")216        .Case("0xd20", "cortex-m23")217        .Case("0xd21", "cortex-m33")218        .Case("0xd24", "cortex-m52")219        .Case("0xd22", "cortex-m55")220        .Case("0xd23", "cortex-m85")221        .Case("0xc18", "cortex-r8")222        .Case("0xd13", "cortex-r52")223        .Case("0xd16", "cortex-r52plus")224        .Case("0xd15", "cortex-r82")225        .Case("0xd14", "cortex-r82ae")226        .Case("0xd02", "cortex-a34")227        .Case("0xd04", "cortex-a35")228        .Case("0xd8f", "cortex-a320")229        .Case("0xd03", "cortex-a53")230        .Case("0xd05", "cortex-a55")231        .Case("0xd46", "cortex-a510")232        .Case("0xd80", "cortex-a520")233        .Case("0xd88", "cortex-a520ae")234        .Case("0xd07", "cortex-a57")235        .Case("0xd06", "cortex-a65")236        .Case("0xd43", "cortex-a65ae")237        .Case("0xd08", "cortex-a72")238        .Case("0xd09", "cortex-a73")239        .Case("0xd0a", "cortex-a75")240        .Case("0xd0b", "cortex-a76")241        .Case("0xd0e", "cortex-a76ae")242        .Case("0xd0d", "cortex-a77")243        .Case("0xd41", "cortex-a78")244        .Case("0xd42", "cortex-a78ae")245        .Case("0xd4b", "cortex-a78c")246        .Case("0xd47", "cortex-a710")247        .Case("0xd4d", "cortex-a715")248        .Case("0xd81", "cortex-a720")249        .Case("0xd89", "cortex-a720ae")250        .Case("0xd87", "cortex-a725")251        .Case("0xd44", "cortex-x1")252        .Case("0xd4c", "cortex-x1c")253        .Case("0xd48", "cortex-x2")254        .Case("0xd4e", "cortex-x3")255        .Case("0xd82", "cortex-x4")256        .Case("0xd85", "cortex-x925")257        .Case("0xd4a", "neoverse-e1")258        .Case("0xd0c", "neoverse-n1")259        .Case("0xd49", "neoverse-n2")260        .Case("0xd8e", "neoverse-n3")261        .Case("0xd40", "neoverse-v1")262        .Case("0xd4f", "neoverse-v2")263        .Case("0xd84", "neoverse-v3")264        .Case("0xd83", "neoverse-v3ae")265        .Default("generic");266  }267 268  if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.269    return StringSwitch<const char *>(Part)270      .Case("0x516", "thunderx2t99")271      .Case("0x0516", "thunderx2t99")272      .Case("0xaf", "thunderx2t99")273      .Case("0x0af", "thunderx2t99")274      .Case("0xa1", "thunderxt88")275      .Case("0x0a1", "thunderxt88")276      .Default("generic");277  }278 279  if (Implementer == "0x46") { // Fujitsu Ltd.280    return StringSwitch<const char *>(Part)281        .Case("0x001", "a64fx")282        .Case("0x003", "fujitsu-monaka")283        .Default("generic");284  }285 286  if (Implementer == "0x4e") { // NVIDIA Corporation287    return StringSwitch<const char *>(Part)288        .Case("0x004", "carmel")289        .Case("0x10", "olympus")290        .Case("0x010", "olympus")291        .Default("generic");292  }293 294  if (Implementer == "0x48") // HiSilicon Technologies, Inc.295    // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The296    // values correspond to the "Part number" in the CP15/c0 register. The297    // contents are specified in the various processor manuals.298    return StringSwitch<const char *>(Part)299      .Case("0xd01", "tsv110")300      .Default("generic");301 302  if (Implementer == "0x51") // Qualcomm Technologies, Inc.303    // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The304    // values correspond to the "Part number" in the CP15/c0 register. The305    // contents are specified in the various processor manuals.306    return StringSwitch<const char *>(Part)307        .Case("0x06f", "krait") // APQ8064308        .Case("0x201", "kryo")309        .Case("0x205", "kryo")310        .Case("0x211", "kryo")311        .Case("0x800", "cortex-a73") // Kryo 2xx Gold312        .Case("0x801", "cortex-a73") // Kryo 2xx Silver313        .Case("0x802", "cortex-a75") // Kryo 3xx Gold314        .Case("0x803", "cortex-a75") // Kryo 3xx Silver315        .Case("0x804", "cortex-a76") // Kryo 4xx Gold316        .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver317        .Case("0xc00", "falkor")318        .Case("0xc01", "saphira")319        .Case("0x001", "oryon-1")320        .Default("generic");321  if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.322    // The Exynos chips have a convoluted ID scheme that doesn't seem to follow323    // any predictive pattern across variants and parts.324 325    // Look for the CPU variant line, whose value is a 1 digit hexadecimal326    // number, corresponding to the Variant bits in the CP15/C0 register.327    unsigned Variant = GetVariant();328 329    // Convert the CPU part line, whose value is a 3 digit hexadecimal number,330    // corresponding to the PartNum bits in the CP15/C0 register.331    unsigned PartAsInt;332    Part.getAsInteger(0, PartAsInt);333 334    unsigned Exynos = (Variant << 12) | PartAsInt;335    switch (Exynos) {336    default:337      // Default by falling through to Exynos M3.338      [[fallthrough]];339    case 0x1002:340      return "exynos-m3";341    case 0x1003:342      return "exynos-m4";343    }344  }345 346  if (Implementer == "0x61") { // Apple347    return StringSwitch<const char *>(Part)348        .Case("0x020", "apple-m1")349        .Case("0x021", "apple-m1")350        .Case("0x022", "apple-m1")351        .Case("0x023", "apple-m1")352        .Case("0x024", "apple-m1")353        .Case("0x025", "apple-m1")354        .Case("0x028", "apple-m1")355        .Case("0x029", "apple-m1")356        .Case("0x030", "apple-m2")357        .Case("0x031", "apple-m2")358        .Case("0x032", "apple-m2")359        .Case("0x033", "apple-m2")360        .Case("0x034", "apple-m2")361        .Case("0x035", "apple-m2")362        .Case("0x038", "apple-m2")363        .Case("0x039", "apple-m2")364        .Case("0x049", "apple-m3")365        .Case("0x048", "apple-m3")366        .Default("generic");367  }368 369  if (Implementer == "0x63") { // Arm China.370    return StringSwitch<const char *>(Part)371        .Case("0x132", "star-mc1")372        .Case("0xd25", "star-mc3")373        .Default("generic");374  }375 376  if (Implementer == "0x6d") { // Microsoft Corporation.377    // The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2.378    return StringSwitch<const char *>(Part)379        .Case("0xd49", "neoverse-n2")380        .Default("generic");381  }382 383  if (Implementer == "0xc0") { // Ampere Computing384    return StringSwitch<const char *>(Part)385        .Case("0xac3", "ampere1")386        .Case("0xac4", "ampere1a")387        .Case("0xac5", "ampere1b")388        .Default("generic");389  }390 391  return "generic";392}393 394StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {395  // The cpuid register on arm is not accessible from user space. On Linux,396  // it is exposed through the /proc/cpuinfo file.397 398  // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line399  // in all cases.400  SmallVector<StringRef, 32> Lines;401  ProcCpuinfoContent.split(Lines, '\n');402 403  // Look for the CPU implementer and hardware lines, and store the CPU part404  // numbers found.405  StringRef Implementer;406  StringRef Hardware;407  SmallVector<StringRef, 32> Parts;408  for (StringRef Line : Lines) {409    if (Line.consume_front("CPU implementer"))410      Implementer = Line.ltrim("\t :");411    else if (Line.consume_front("Hardware"))412      Hardware = Line.ltrim("\t :");413    else if (Line.consume_front("CPU part"))414      Parts.emplace_back(Line.ltrim("\t :"));415  }416 417  // Last `Part' seen, in case we don't analyse all `Parts' parsed.418  StringRef Part = Parts.empty() ? StringRef() : Parts.back();419 420  // Remove duplicate `Parts'.421  llvm::sort(Parts);422  Parts.erase(llvm::unique(Parts), Parts.end());423 424  auto GetVariant = [&]() {425    unsigned Variant = 0;426    for (auto I : Lines)427      if (I.consume_front("CPU variant"))428        I.ltrim("\t :").getAsInteger(0, Variant);429    return Variant;430  };431 432  return getHostCPUNameForARMFromComponents(Implementer, Hardware, Part, Parts,433                                            GetVariant);434}435 436StringRef sys::detail::getHostCPUNameForARM(uint64_t PrimaryCpuInfo,437                                            ArrayRef<uint64_t> UniqueCpuInfos) {438  // On Windows, the registry provides cached copied of the MIDR_EL1 register.439  using PartNum = Bitfield::Element<uint16_t, 4, 12>;440  using Implementer = Bitfield::Element<uint16_t, 24, 8>;441  using Variant = Bitfield::Element<uint16_t, 20, 4>;442 443  SmallVector<std::string> PartsHolder;444  PartsHolder.reserve(UniqueCpuInfos.size());445  for (auto Info : UniqueCpuInfos)446    PartsHolder.push_back("0x" + utohexstr(Bitfield::get<PartNum>(Info),447                                           /*LowerCase*/ true,448                                           /*Width*/ 3));449 450  SmallVector<StringRef> Parts;451  Parts.reserve(PartsHolder.size());452  for (const auto &Part : PartsHolder)453    Parts.push_back(Part);454 455  return getHostCPUNameForARMFromComponents(456      "0x" + utohexstr(Bitfield::get<Implementer>(PrimaryCpuInfo),457                       /*LowerCase*/ true,458                       /*Width*/ 2),459      /*Hardware*/ "",460      "0x" + utohexstr(Bitfield::get<PartNum>(PrimaryCpuInfo),461                       /*LowerCase*/ true,462                       /*Width*/ 3),463      Parts, [=]() { return Bitfield::get<Variant>(PrimaryCpuInfo); });464}465 466namespace {467StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {468  switch (Id) {469    case 2064:  // z900 not supported by LLVM470    case 2066:471    case 2084:  // z990 not supported by LLVM472    case 2086:473    case 2094:  // z9-109 not supported by LLVM474    case 2096:475      return "generic";476    case 2097:477    case 2098:478      return "z10";479    case 2817:480    case 2818:481      return "z196";482    case 2827:483    case 2828:484      return "zEC12";485    case 2964:486    case 2965:487      return HaveVectorSupport? "z13" : "zEC12";488    case 3906:489    case 3907:490      return HaveVectorSupport? "z14" : "zEC12";491    case 8561:492    case 8562:493      return HaveVectorSupport? "z15" : "zEC12";494    case 3931:495    case 3932:496      return HaveVectorSupport? "z16" : "zEC12";497    case 9175:498    case 9176:499    default:500      return HaveVectorSupport? "z17" : "zEC12";501  }502}503} // end anonymous namespace504 505StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {506  // STIDP is a privileged operation, so use /proc/cpuinfo instead.507 508  // The "processor 0:" line comes after a fair amount of other information,509  // including a cache breakdown, but this should be plenty.510  SmallVector<StringRef, 32> Lines;511  ProcCpuinfoContent.split(Lines, '\n');512 513  // Look for the CPU features.514  SmallVector<StringRef, 32> CPUFeatures;515  for (StringRef Line : Lines)516    if (Line.starts_with("features")) {517      size_t Pos = Line.find(':');518      if (Pos != StringRef::npos) {519        Line.drop_front(Pos + 1).split(CPUFeatures, ' ');520        break;521      }522    }523 524  // We need to check for the presence of vector support independently of525  // the machine type, since we may only use the vector register set when526  // supported by the kernel (and hypervisor).527  bool HaveVectorSupport = llvm::is_contained(CPUFeatures, "vx");528 529  // Now check the processor machine type.530  for (StringRef Line : Lines) {531    if (Line.starts_with("processor ")) {532      size_t Pos = Line.find("machine = ");533      if (Pos != StringRef::npos) {534        Pos += sizeof("machine = ") - 1;535        unsigned int Id;536        if (!Line.drop_front(Pos).getAsInteger(10, Id))537          return getCPUNameFromS390Model(Id, HaveVectorSupport);538      }539      break;540    }541  }542 543  return "generic";544}545 546StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {547  // There are 24 lines in /proc/cpuinfo548  SmallVector<StringRef> Lines;549  ProcCpuinfoContent.split(Lines, '\n');550 551  // Look for uarch line to determine cpu name552  StringRef UArch;553  for (StringRef Line : Lines) {554    if (Line.starts_with("uarch")) {555      UArch = Line.substr(5).ltrim("\t :");556      break;557    }558  }559 560  return StringSwitch<const char *>(UArch)561      .Case("eswin,eic770x", "sifive-p550")562      .Case("sifive,u74-mc", "sifive-u74")563      .Case("sifive,bullet0", "sifive-u74")564      .Default("");565}566 567StringRef sys::detail::getHostCPUNameForBPF() {568#if !defined(__linux__) || !defined(__x86_64__)569  return "generic";570#else571  uint8_t v3_insns[40] __attribute__ ((aligned (8))) =572      /* BPF_MOV64_IMM(BPF_REG_0, 0) */573    { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,574      /* BPF_MOV64_IMM(BPF_REG_2, 1) */575      0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,576      /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */577      0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,578      /* BPF_MOV64_IMM(BPF_REG_0, 1) */579      0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,580      /* BPF_EXIT_INSN() */581      0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };582 583  uint8_t v2_insns[40] __attribute__ ((aligned (8))) =584      /* BPF_MOV64_IMM(BPF_REG_0, 0) */585    { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,586      /* BPF_MOV64_IMM(BPF_REG_2, 1) */587      0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,588      /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */589      0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,590      /* BPF_MOV64_IMM(BPF_REG_0, 1) */591      0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,592      /* BPF_EXIT_INSN() */593      0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };594 595  struct bpf_prog_load_attr {596    uint32_t prog_type;597    uint32_t insn_cnt;598    uint64_t insns;599    uint64_t license;600    uint32_t log_level;601    uint32_t log_size;602    uint64_t log_buf;603    uint32_t kern_version;604    uint32_t prog_flags;605  } attr = {};606  attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */607  attr.insn_cnt = 5;608  attr.insns = (uint64_t)v3_insns;609  attr.license = (uint64_t)"DUMMY";610 611  int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,612                   sizeof(attr));613  if (fd >= 0) {614    close(fd);615    return "v3";616  }617 618  /* Clear the whole attr in case its content changed by syscall. */619  memset(&attr, 0, sizeof(attr));620  attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */621  attr.insn_cnt = 5;622  attr.insns = (uint64_t)v2_insns;623  attr.license = (uint64_t)"DUMMY";624  fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));625  if (fd >= 0) {626    close(fd);627    return "v2";628  }629  return "v1";630#endif631}632 633#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) ||           \634     defined(_M_X64)) &&                                                       \635    !defined(_M_ARM64EC)636 637/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in638/// the specified arguments.  If we can't run cpuid on the host, return true.639static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,640                               unsigned *rECX, unsigned *rEDX) {641#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)642  return !__get_cpuid(value, rEAX, rEBX, rECX, rEDX);643#elif defined(_MSC_VER)644  // The MSVC intrinsic is portable across x86 and x64.645  int registers[4];646  __cpuid(registers, value);647  *rEAX = registers[0];648  *rEBX = registers[1];649  *rECX = registers[2];650  *rEDX = registers[3];651  return false;652#else653  return true;654#endif655}656 657namespace llvm {658namespace sys {659namespace detail {660namespace x86 {661 662VendorSignatures getVendorSignature(unsigned *MaxLeaf) {663  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;664  if (MaxLeaf == nullptr)665    MaxLeaf = &EAX;666  else667    *MaxLeaf = 0;668 669  if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)670    return VendorSignatures::UNKNOWN;671 672  // "Genu ineI ntel"673  if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)674    return VendorSignatures::GENUINE_INTEL;675 676  // "Auth enti cAMD"677  if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)678    return VendorSignatures::AUTHENTIC_AMD;679 680  return VendorSignatures::UNKNOWN;681}682 683} // namespace x86684} // namespace detail685} // namespace sys686} // namespace llvm687 688using namespace llvm::sys::detail::x86;689 690/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return691/// the 4 values in the specified arguments.  If we can't run cpuid on the host,692/// return true.693static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,694                                 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,695                                 unsigned *rEDX) {696  // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang697  // are such that __cpuidex is defined within cpuid.h for both, we can remove698  // the __get_cpuid_count function and share the MSVC implementation between699  // all three.700#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)701  return !__get_cpuid_count(value, subleaf, rEAX, rEBX, rECX, rEDX);702#elif defined(_MSC_VER)703  int registers[4];704  __cpuidex(registers, value, subleaf);705  *rEAX = registers[0];706  *rEBX = registers[1];707  *rECX = registers[2];708  *rEDX = registers[3];709  return false;710#else711  return true;712#endif713}714 715// Read control register 0 (XCR0). Used to detect features such as AVX.716static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {717  // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang718  // are such that _xgetbv is supported by both, we can unify the implementation719  // with MSVC and remove all inline assembly.720#if defined(__GNUC__) || defined(__clang__)721  // Check xgetbv; this uses a .byte sequence instead of the instruction722  // directly because older assemblers do not include support for xgetbv and723  // there is no easy way to conditionally compile based on the assembler used.724  __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));725  return false;726#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)727  unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);728  *rEAX = Result;729  *rEDX = Result >> 32;730  return false;731#else732  return true;733#endif734}735 736static void detectX86FamilyModel(unsigned EAX, unsigned *Family,737                                 unsigned *Model) {738  *Family = (EAX >> 8) & 0xf; // Bits 8 - 11739  *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7740  if (*Family == 6 || *Family == 0xf) {741    if (*Family == 0xf)742      // Examine extended family ID if family ID is F.743      *Family += (EAX >> 20) & 0xff; // Bits 20 - 27744    // Examine extended model ID if family ID is 6 or F.745    *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19746  }747}748 749#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0750 751static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,752                                                 unsigned Model,753                                                 const unsigned *Features,754                                                 unsigned *Type,755                                                 unsigned *Subtype) {756  StringRef CPU;757 758  switch (Family) {759  case 0x3:760    CPU = "i386";761    break;762  case 0x4:763    CPU = "i486";764    break;765  case 0x5:766    if (testFeature(X86::FEATURE_MMX)) {767      CPU = "pentium-mmx";768      break;769    }770    CPU = "pentium";771    break;772  case 0x6:773    switch (Model) {774    case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile775               // processor, Intel Core 2 Quad processor, Intel Core 2 Quad776               // mobile processor, Intel Core 2 Extreme processor, Intel777               // Pentium Dual-Core processor, Intel Xeon processor, model778               // 0Fh. All processors are manufactured using the 65 nm process.779    case 0x16: // Intel Celeron processor model 16h. All processors are780               // manufactured using the 65 nm process781      CPU = "core2";782      *Type = X86::INTEL_CORE2;783      break;784    case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model785               // 17h. All processors are manufactured using the 45 nm process.786               //787               // 45nm: Penryn , Wolfdale, Yorkfield (XE)788    case 0x1d: // Intel Xeon processor MP. All processors are manufactured using789               // the 45 nm process.790      CPU = "penryn";791      *Type = X86::INTEL_CORE2;792      break;793    case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All794               // processors are manufactured using the 45 nm process.795    case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.796               // As found in a Summer 2010 model iMac.797    case 0x1f:798    case 0x2e:              // Nehalem EX799      CPU = "nehalem";800      *Type = X86::INTEL_COREI7;801      *Subtype = X86::INTEL_COREI7_NEHALEM;802      break;803    case 0x25: // Intel Core i7, laptop version.804    case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All805               // processors are manufactured using the 32 nm process.806    case 0x2f: // Westmere EX807      CPU = "westmere";808      *Type = X86::INTEL_COREI7;809      *Subtype = X86::INTEL_COREI7_WESTMERE;810      break;811    case 0x2a: // Intel Core i7 processor. All processors are manufactured812               // using the 32 nm process.813    case 0x2d:814      CPU = "sandybridge";815      *Type = X86::INTEL_COREI7;816      *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;817      break;818    case 0x3a:819    case 0x3e:              // Ivy Bridge EP820      CPU = "ivybridge";821      *Type = X86::INTEL_COREI7;822      *Subtype = X86::INTEL_COREI7_IVYBRIDGE;823      break;824 825    // Haswell:826    case 0x3c:827    case 0x3f:828    case 0x45:829    case 0x46:830      CPU = "haswell";831      *Type = X86::INTEL_COREI7;832      *Subtype = X86::INTEL_COREI7_HASWELL;833      break;834 835    // Broadwell:836    case 0x3d:837    case 0x47:838    case 0x4f:839    case 0x56:840      CPU = "broadwell";841      *Type = X86::INTEL_COREI7;842      *Subtype = X86::INTEL_COREI7_BROADWELL;843      break;844 845    // Skylake:846    case 0x4e:              // Skylake mobile847    case 0x5e:              // Skylake desktop848    case 0x8e:              // Kaby Lake mobile849    case 0x9e:              // Kaby Lake desktop850    case 0xa5:              // Comet Lake-H/S851    case 0xa6:              // Comet Lake-U852      CPU = "skylake";853      *Type = X86::INTEL_COREI7;854      *Subtype = X86::INTEL_COREI7_SKYLAKE;855      break;856 857    // Rocketlake:858    case 0xa7:859      CPU = "rocketlake";860      *Type = X86::INTEL_COREI7;861      *Subtype = X86::INTEL_COREI7_ROCKETLAKE;862      break;863 864    // Skylake Xeon:865    case 0x55:866      *Type = X86::INTEL_COREI7;867      if (testFeature(X86::FEATURE_AVX512BF16)) {868        CPU = "cooperlake";869        *Subtype = X86::INTEL_COREI7_COOPERLAKE;870      } else if (testFeature(X86::FEATURE_AVX512VNNI)) {871        CPU = "cascadelake";872        *Subtype = X86::INTEL_COREI7_CASCADELAKE;873      } else {874        CPU = "skylake-avx512";875        *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;876      }877      break;878 879    // Cannonlake:880    case 0x66:881      CPU = "cannonlake";882      *Type = X86::INTEL_COREI7;883      *Subtype = X86::INTEL_COREI7_CANNONLAKE;884      break;885 886    // Icelake:887    case 0x7d:888    case 0x7e:889      CPU = "icelake-client";890      *Type = X86::INTEL_COREI7;891      *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;892      break;893 894    // Tigerlake:895    case 0x8c:896    case 0x8d:897      CPU = "tigerlake";898      *Type = X86::INTEL_COREI7;899      *Subtype = X86::INTEL_COREI7_TIGERLAKE;900      break;901 902    // Alderlake:903    case 0x97:904    case 0x9a:905      CPU = "alderlake";906      *Type = X86::INTEL_COREI7;907      *Subtype = X86::INTEL_COREI7_ALDERLAKE;908      break;909 910    // Gracemont911    case 0xbe:912      CPU = "gracemont";913      *Type = X86::INTEL_COREI7;914      *Subtype = X86::INTEL_COREI7_ALDERLAKE;915      break;916 917    // Raptorlake:918    case 0xb7:919    case 0xba:920    case 0xbf:921      CPU = "raptorlake";922      *Type = X86::INTEL_COREI7;923      *Subtype = X86::INTEL_COREI7_ALDERLAKE;924      break;925 926    // Meteorlake:927    case 0xaa:928    case 0xac:929      CPU = "meteorlake";930      *Type = X86::INTEL_COREI7;931      *Subtype = X86::INTEL_COREI7_ALDERLAKE;932      break;933 934    // Arrowlake:935    case 0xc5:936    // Arrowlake U:937    case 0xb5:938      CPU = "arrowlake";939      *Type = X86::INTEL_COREI7;940      *Subtype = X86::INTEL_COREI7_ARROWLAKE;941      break;942 943    // Arrowlake S:944    case 0xc6:945      CPU = "arrowlake-s";946      *Type = X86::INTEL_COREI7;947      *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;948      break;949 950    // Lunarlake:951    case 0xbd:952      CPU = "lunarlake";953      *Type = X86::INTEL_COREI7;954      *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;955      break;956 957    // Pantherlake:958    case 0xcc:959      CPU = "pantherlake";960      *Type = X86::INTEL_COREI7;961      *Subtype = X86::INTEL_COREI7_PANTHERLAKE;962      break;963 964    // Wildcatlake:965    case 0xd5:966      CPU = "wildcatlake";967      *Type = X86::INTEL_COREI7;968      *Subtype = X86::INTEL_COREI7_PANTHERLAKE;969      break;970 971    // Graniterapids:972    case 0xad:973      CPU = "graniterapids";974      *Type = X86::INTEL_COREI7;975      *Subtype = X86::INTEL_COREI7_GRANITERAPIDS;976      break;977 978    // Granite Rapids D:979    case 0xae:980      CPU = "graniterapids-d";981      *Type = X86::INTEL_COREI7;982      *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;983      break;984 985    // Icelake Xeon:986    case 0x6a:987    case 0x6c:988      CPU = "icelake-server";989      *Type = X86::INTEL_COREI7;990      *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;991      break;992 993    // Emerald Rapids:994    case 0xcf:995      CPU = "emeraldrapids";996      *Type = X86::INTEL_COREI7;997      *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;998      break;999 1000    // Sapphire Rapids:1001    case 0x8f:1002      CPU = "sapphirerapids";1003      *Type = X86::INTEL_COREI7;1004      *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;1005      break;1006 1007    case 0x1c: // Most 45 nm Intel Atom processors1008    case 0x26: // 45 nm Atom Lincroft1009    case 0x27: // 32 nm Atom Medfield1010    case 0x35: // 32 nm Atom Midview1011    case 0x36: // 32 nm Atom Midview1012      CPU = "bonnell";1013      *Type = X86::INTEL_BONNELL;1014      break;1015 1016    // Atom Silvermont codes from the Intel software optimization guide.1017    case 0x37:1018    case 0x4a:1019    case 0x4d:1020    case 0x5a:1021    case 0x5d:1022    case 0x4c: // really airmont1023      CPU = "silvermont";1024      *Type = X86::INTEL_SILVERMONT;1025      break;1026    // Goldmont:1027    case 0x5c: // Apollo Lake1028    case 0x5f: // Denverton1029      CPU = "goldmont";1030      *Type = X86::INTEL_GOLDMONT;1031      break;1032    case 0x7a:1033      CPU = "goldmont-plus";1034      *Type = X86::INTEL_GOLDMONT_PLUS;1035      break;1036    case 0x86:1037    case 0x8a: // Lakefield1038    case 0x96: // Elkhart Lake1039    case 0x9c: // Jasper Lake1040      CPU = "tremont";1041      *Type = X86::INTEL_TREMONT;1042      break;1043 1044    // Sierraforest:1045    case 0xaf:1046      CPU = "sierraforest";1047      *Type = X86::INTEL_SIERRAFOREST;1048      break;1049 1050    // Grandridge:1051    case 0xb6:1052      CPU = "grandridge";1053      *Type = X86::INTEL_GRANDRIDGE;1054      break;1055 1056    // Clearwaterforest:1057    case 0xdd:1058      CPU = "clearwaterforest";1059      *Type = X86::INTEL_CLEARWATERFOREST;1060      break;1061 1062    // Xeon Phi (Knights Landing + Knights Mill):1063    case 0x57:1064      CPU = "knl";1065      *Type = X86::INTEL_KNL;1066      break;1067    case 0x85:1068      CPU = "knm";1069      *Type = X86::INTEL_KNM;1070      break;1071 1072    default: // Unknown family 6 CPU, try to guess.1073      // Don't both with Type/Subtype here, they aren't used by the caller.1074      // They're used above to keep the code in sync with compiler-rt.1075      // TODO detect tigerlake host from model1076      if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {1077        CPU = "tigerlake";1078      } else if (testFeature(X86::FEATURE_AVX512VBMI2)) {1079        CPU = "icelake-client";1080      } else if (testFeature(X86::FEATURE_AVX512VBMI)) {1081        CPU = "cannonlake";1082      } else if (testFeature(X86::FEATURE_AVX512BF16)) {1083        CPU = "cooperlake";1084      } else if (testFeature(X86::FEATURE_AVX512VNNI)) {1085        CPU = "cascadelake";1086      } else if (testFeature(X86::FEATURE_AVX512VL)) {1087        CPU = "skylake-avx512";1088      } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {1089        if (testFeature(X86::FEATURE_SHA))1090          CPU = "goldmont";1091        else1092          CPU = "skylake";1093      } else if (testFeature(X86::FEATURE_ADX)) {1094        CPU = "broadwell";1095      } else if (testFeature(X86::FEATURE_AVX2)) {1096        CPU = "haswell";1097      } else if (testFeature(X86::FEATURE_AVX)) {1098        CPU = "sandybridge";1099      } else if (testFeature(X86::FEATURE_SSE4_2)) {1100        if (testFeature(X86::FEATURE_MOVBE))1101          CPU = "silvermont";1102        else1103          CPU = "nehalem";1104      } else if (testFeature(X86::FEATURE_SSE4_1)) {1105        CPU = "penryn";1106      } else if (testFeature(X86::FEATURE_SSSE3)) {1107        if (testFeature(X86::FEATURE_MOVBE))1108          CPU = "bonnell";1109        else1110          CPU = "core2";1111      } else if (testFeature(X86::FEATURE_64BIT)) {1112        CPU = "core2";1113      } else if (testFeature(X86::FEATURE_SSE3)) {1114        CPU = "yonah";1115      } else if (testFeature(X86::FEATURE_SSE2)) {1116        CPU = "pentium-m";1117      } else if (testFeature(X86::FEATURE_SSE)) {1118        CPU = "pentium3";1119      } else if (testFeature(X86::FEATURE_MMX)) {1120        CPU = "pentium2";1121      } else {1122        CPU = "pentiumpro";1123      }1124      break;1125    }1126    break;1127  case 0xf: {1128    if (testFeature(X86::FEATURE_64BIT)) {1129      CPU = "nocona";1130      break;1131    }1132    if (testFeature(X86::FEATURE_SSE3)) {1133      CPU = "prescott";1134      break;1135    }1136    CPU = "pentium4";1137    break;1138  }1139  case 0x13:1140    switch (Model) {1141    // Diamond Rapids:1142    case 0x01:1143      CPU = "diamondrapids";1144      *Type = X86::INTEL_COREI7;1145      *Subtype = X86::INTEL_COREI7_DIAMONDRAPIDS;1146      break;1147 1148    default: // Unknown family 19 CPU.1149      break;1150    }1151    break;1152  case 0x12:1153    switch (Model) {1154    // Novalake:1155    case 0x1:1156    case 0x3:1157      CPU = "novalake";1158      *Type = X86::INTEL_COREI7;1159      *Subtype = X86::INTEL_COREI7_NOVALAKE;1160      break;1161    default: // Unknown family 0x12 CPU.1162      break;1163    }1164    break;1165 1166  default:1167    break; // Unknown.1168  }1169 1170  return CPU;1171}1172 1173static const char *getAMDProcessorTypeAndSubtype(unsigned Family,1174                                                 unsigned Model,1175                                                 const unsigned *Features,1176                                                 unsigned *Type,1177                                                 unsigned *Subtype) {1178  const char *CPU = nullptr;1179 1180  switch (Family) {1181  case 4:1182    CPU = "i486";1183    break;1184  case 5:1185    CPU = "pentium";1186    switch (Model) {1187    case 6:1188    case 7:1189      CPU = "k6";1190      break;1191    case 8:1192      CPU = "k6-2";1193      break;1194    case 9:1195    case 13:1196      CPU = "k6-3";1197      break;1198    case 10:1199      CPU = "geode";1200      break;1201    }1202    break;1203  case 6:1204    if (testFeature(X86::FEATURE_SSE)) {1205      CPU = "athlon-xp";1206      break;1207    }1208    CPU = "athlon";1209    break;1210  case 15:1211    if (testFeature(X86::FEATURE_SSE3)) {1212      CPU = "k8-sse3";1213      break;1214    }1215    CPU = "k8";1216    break;1217  case 16:1218  case 18:1219    CPU = "amdfam10";1220    *Type = X86::AMDFAM10H; // "amdfam10"1221    switch (Model) {1222    case 2:1223      *Subtype = X86::AMDFAM10H_BARCELONA;1224      break;1225    case 4:1226      *Subtype = X86::AMDFAM10H_SHANGHAI;1227      break;1228    case 8:1229      *Subtype = X86::AMDFAM10H_ISTANBUL;1230      break;1231    }1232    break;1233  case 20:1234    CPU = "btver1";1235    *Type = X86::AMD_BTVER1;1236    break;1237  case 21:1238    CPU = "bdver1";1239    *Type = X86::AMDFAM15H;1240    if (Model >= 0x60 && Model <= 0x7f) {1241      CPU = "bdver4";1242      *Subtype = X86::AMDFAM15H_BDVER4;1243      break; // 60h-7Fh: Excavator1244    }1245    if (Model >= 0x30 && Model <= 0x3f) {1246      CPU = "bdver3";1247      *Subtype = X86::AMDFAM15H_BDVER3;1248      break; // 30h-3Fh: Steamroller1249    }1250    if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {1251      CPU = "bdver2";1252      *Subtype = X86::AMDFAM15H_BDVER2;1253      break; // 02h, 10h-1Fh: Piledriver1254    }1255    if (Model <= 0x0f) {1256      *Subtype = X86::AMDFAM15H_BDVER1;1257      break; // 00h-0Fh: Bulldozer1258    }1259    break;1260  case 22:1261    CPU = "btver2";1262    *Type = X86::AMD_BTVER2;1263    break;1264  case 23:1265    CPU = "znver1";1266    *Type = X86::AMDFAM17H;1267    if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||1268        (Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) ||1269        (Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) ||1270        (Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) ||1271        (Model >= 0xa0 && Model <= 0xaf)) {1272      // Family 17h Models 30h-3Fh (Starship) Zen 21273      // Family 17h Models 47h (Cardinal) Zen 21274      // Family 17h Models 60h-67h (Renoir) Zen 21275      // Family 17h Models 68h-6Fh (Lucienne) Zen 21276      // Family 17h Models 70h-7Fh (Matisse) Zen 21277      // Family 17h Models 84h-87h (ProjectX) Zen 21278      // Family 17h Models 90h-97h (VanGogh) Zen 21279      // Family 17h Models 98h-9Fh (Mero) Zen 21280      // Family 17h Models A0h-AFh (Mendocino) Zen 21281      CPU = "znver2";1282      *Subtype = X86::AMDFAM17H_ZNVER2;1283      break;1284    }1285    if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) {1286      // Family 17h Models 10h-1Fh (Raven1) Zen1287      // Family 17h Models 10h-1Fh (Picasso) Zen+1288      // Family 17h Models 20h-2Fh (Raven2 x86) Zen1289      *Subtype = X86::AMDFAM17H_ZNVER1;1290      break;1291    }1292    break;1293  case 25:1294    CPU = "znver3";1295    *Type = X86::AMDFAM19H;1296    if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||1297        (Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||1298        (Model >= 0x50 && Model <= 0x5f)) {1299      // Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 31300      // Family 19h Models 20h-2Fh (Vermeer) Zen 31301      // Family 19h Models 30h-3Fh (Badami) Zen 31302      // Family 19h Models 40h-4Fh (Rembrandt) Zen 3+1303      // Family 19h Models 50h-5Fh (Cezanne) Zen 31304      *Subtype = X86::AMDFAM19H_ZNVER3;1305      break;1306    }1307    if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) ||1308        (Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) ||1309        (Model >= 0xa0 && Model <= 0xaf)) {1310      // Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 41311      // Family 19h Models 60h-6Fh (Raphael) Zen 41312      // Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 41313      // Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 41314      // Family 19h Models A0h-AFh (Stones-Dense) Zen 41315      CPU = "znver4";1316      *Subtype = X86::AMDFAM19H_ZNVER4;1317      break; //  "znver4"1318    }1319    break; // family 19h1320  case 26:1321    CPU = "znver5";1322    *Type = X86::AMDFAM1AH;1323    if (Model <= 0x4f || (Model >= 0x60 && Model <= 0x77) ||1324        (Model >= 0xd0 && Model <= 0xd7)) {1325      // Models 00h-0Fh (Breithorn).1326      // Models 10h-1Fh (Breithorn-Dense).1327      // Models 20h-2Fh (Strix 1).1328      // Models 30h-37h (Strix 2).1329      // Models 38h-3Fh (Strix 3).1330      // Models 40h-4Fh (Granite Ridge).1331      // Models 60h-6Fh (Krackan1).1332      // Models 70h-77h (Sarlak).1333      // Models D0h-D7h (Annapurna).1334      CPU = "znver5";1335      *Subtype = X86::AMDFAM1AH_ZNVER5;1336      break; //  "znver5"1337    }1338    break;1339 1340  default:1341    break; // Unknown AMD CPU.1342  }1343 1344  return CPU;1345}1346 1347#undef testFeature1348 1349static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,1350                                 unsigned *Features) {1351  unsigned EAX, EBX;1352 1353  auto setFeature = [&](unsigned F) {1354    Features[F / 32] |= 1U << (F % 32);1355  };1356 1357  if ((EDX >> 15) & 1)1358    setFeature(X86::FEATURE_CMOV);1359  if ((EDX >> 23) & 1)1360    setFeature(X86::FEATURE_MMX);1361  if ((EDX >> 25) & 1)1362    setFeature(X86::FEATURE_SSE);1363  if ((EDX >> 26) & 1)1364    setFeature(X86::FEATURE_SSE2);1365 1366  if ((ECX >> 0) & 1)1367    setFeature(X86::FEATURE_SSE3);1368  if ((ECX >> 1) & 1)1369    setFeature(X86::FEATURE_PCLMUL);1370  if ((ECX >> 9) & 1)1371    setFeature(X86::FEATURE_SSSE3);1372  if ((ECX >> 12) & 1)1373    setFeature(X86::FEATURE_FMA);1374  if ((ECX >> 19) & 1)1375    setFeature(X86::FEATURE_SSE4_1);1376  if ((ECX >> 20) & 1) {1377    setFeature(X86::FEATURE_SSE4_2);1378    setFeature(X86::FEATURE_CRC32);1379  }1380  if ((ECX >> 23) & 1)1381    setFeature(X86::FEATURE_POPCNT);1382  if ((ECX >> 25) & 1)1383    setFeature(X86::FEATURE_AES);1384 1385  if ((ECX >> 22) & 1)1386    setFeature(X86::FEATURE_MOVBE);1387 1388  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV1389  // indicates that the AVX registers will be saved and restored on context1390  // switch, then we have full AVX support.1391  const unsigned AVXBits = (1 << 27) | (1 << 28);1392  bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&1393                ((EAX & 0x6) == 0x6);1394#if defined(__APPLE__)1395  // Darwin lazily saves the AVX512 context on first use: trust that the OS will1396  // save the AVX512 context if we use AVX512 instructions, even the bit is not1397  // set right now.1398  bool HasAVX512Save = true;1399#else1400  // AVX512 requires additional context to be saved by the OS.1401  bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);1402#endif1403 1404  if (HasAVX)1405    setFeature(X86::FEATURE_AVX);1406 1407  bool HasLeaf7 =1408      MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);1409 1410  if (HasLeaf7 && ((EBX >> 3) & 1))1411    setFeature(X86::FEATURE_BMI);1412  if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)1413    setFeature(X86::FEATURE_AVX2);1414  if (HasLeaf7 && ((EBX >> 8) & 1))1415    setFeature(X86::FEATURE_BMI2);1416  if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) {1417    setFeature(X86::FEATURE_AVX512F);1418  }1419  if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)1420    setFeature(X86::FEATURE_AVX512DQ);1421  if (HasLeaf7 && ((EBX >> 19) & 1))1422    setFeature(X86::FEATURE_ADX);1423  if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)1424    setFeature(X86::FEATURE_AVX512IFMA);1425  if (HasLeaf7 && ((EBX >> 23) & 1))1426    setFeature(X86::FEATURE_CLFLUSHOPT);1427  if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)1428    setFeature(X86::FEATURE_AVX512CD);1429  if (HasLeaf7 && ((EBX >> 29) & 1))1430    setFeature(X86::FEATURE_SHA);1431  if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)1432    setFeature(X86::FEATURE_AVX512BW);1433  if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)1434    setFeature(X86::FEATURE_AVX512VL);1435 1436  if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)1437    setFeature(X86::FEATURE_AVX512VBMI);1438  if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)1439    setFeature(X86::FEATURE_AVX512VBMI2);1440  if (HasLeaf7 && ((ECX >> 8) & 1))1441    setFeature(X86::FEATURE_GFNI);1442  if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)1443    setFeature(X86::FEATURE_VPCLMULQDQ);1444  if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)1445    setFeature(X86::FEATURE_AVX512VNNI);1446  if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)1447    setFeature(X86::FEATURE_AVX512BITALG);1448  if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)1449    setFeature(X86::FEATURE_AVX512VPOPCNTDQ);1450 1451  if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)1452    setFeature(X86::FEATURE_AVX5124VNNIW);1453  if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)1454    setFeature(X86::FEATURE_AVX5124FMAPS);1455  if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)1456    setFeature(X86::FEATURE_AVX512VP2INTERSECT);1457 1458  // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't1459  // return all 0s for invalid subleaves so check the limit.1460  bool HasLeaf7Subleaf1 =1461      HasLeaf7 && EAX >= 1 &&1462      !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);1463  if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)1464    setFeature(X86::FEATURE_AVX512BF16);1465 1466  unsigned MaxExtLevel;1467  getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);1468 1469  bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&1470                     !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);1471  if (HasExtLeaf1 && ((ECX >> 6) & 1))1472    setFeature(X86::FEATURE_SSE4_A);1473  if (HasExtLeaf1 && ((ECX >> 11) & 1))1474    setFeature(X86::FEATURE_XOP);1475  if (HasExtLeaf1 && ((ECX >> 16) & 1))1476    setFeature(X86::FEATURE_FMA4);1477 1478  if (HasExtLeaf1 && ((EDX >> 29) & 1))1479    setFeature(X86::FEATURE_64BIT);1480}1481 1482StringRef sys::getHostCPUName() {1483  unsigned MaxLeaf = 0;1484  const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);1485  if (Vendor == VendorSignatures::UNKNOWN)1486    return "generic";1487 1488  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;1489  getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);1490 1491  unsigned Family = 0, Model = 0;1492  unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};1493  detectX86FamilyModel(EAX, &Family, &Model);1494  getAvailableFeatures(ECX, EDX, MaxLeaf, Features);1495 1496  // These aren't consumed in this file, but we try to keep some source code the1497  // same or similar to compiler-rt.1498  unsigned Type = 0;1499  unsigned Subtype = 0;1500 1501  StringRef CPU;1502 1503  if (Vendor == VendorSignatures::GENUINE_INTEL) {1504    CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,1505                                          &Subtype);1506  } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {1507    CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,1508                                        &Subtype);1509  }1510 1511  if (!CPU.empty())1512    return CPU;1513 1514  return "generic";1515}1516 1517#elif defined(_M_ARM64) || defined(_M_ARM64EC)1518 1519StringRef sys::getHostCPUName() {1520  constexpr char CentralProcessorKeyName[] =1521      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor";1522  // Sub keys names are simple numbers ("0", "1", etc.) so 10 chars should be1523  // enough for the slash and name.1524  constexpr size_t SubKeyNameMaxSize = ARRAYSIZE(CentralProcessorKeyName) + 10;1525 1526  SmallVector<uint64_t> Values;1527  uint64_t PrimaryCpuInfo;1528  char PrimaryPartKeyName[SubKeyNameMaxSize];1529  DWORD PrimaryPartKeyNameSize = 0;1530  HKEY CentralProcessorKey;1531  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, CentralProcessorKeyName, 0, KEY_READ,1532                    &CentralProcessorKey) == ERROR_SUCCESS) {1533    for (unsigned Index = 0; Index < UINT32_MAX; ++Index) {1534      char SubKeyName[SubKeyNameMaxSize];1535      DWORD SubKeySize = SubKeyNameMaxSize;1536      HKEY SubKey;1537      if ((RegEnumKeyExA(CentralProcessorKey, Index, SubKeyName, &SubKeySize,1538                         nullptr, nullptr, nullptr,1539                         nullptr) == ERROR_SUCCESS) &&1540          (RegOpenKeyExA(CentralProcessorKey, SubKeyName, 0, KEY_READ,1541                         &SubKey) == ERROR_SUCCESS)) {1542        // The "CP 4000" registry key contains a cached copy of the MIDR_EL11543        // register.1544        uint64_t RegValue;1545        DWORD ActualType;1546        DWORD RegValueSize = sizeof(RegValue);1547        if ((RegQueryValueExA(SubKey, "CP 4000", nullptr, &ActualType,1548                              (PBYTE)&RegValue,1549                              &RegValueSize) == ERROR_SUCCESS) &&1550            (ActualType == REG_QWORD) && RegValueSize == sizeof(RegValue)) {1551          // Assume that the part with the "highest" reg key name is the primary1552          // part (to match the way that Linux's cpuinfo is written). Win321553          // makes no guarantees about the order of sub keys, so we have to1554          // compare the names.1555          if (PrimaryPartKeyNameSize < SubKeySize ||1556              (PrimaryPartKeyNameSize == SubKeySize &&1557               ::memcmp(SubKeyName, PrimaryPartKeyName, SubKeySize) > 0)) {1558            PrimaryCpuInfo = RegValue;1559            ::memcpy(PrimaryPartKeyName, SubKeyName, SubKeySize + 1);1560            PrimaryPartKeyNameSize = SubKeySize;1561          }1562          if (!llvm::is_contained(Values, RegValue)) {1563            Values.push_back(RegValue);1564          }1565        }1566        RegCloseKey(SubKey);1567      } else {1568        // No more sub keys.1569        break;1570      }1571    }1572    RegCloseKey(CentralProcessorKey);1573  }1574 1575  if (Values.empty()) {1576    return "generic";1577  }1578 1579  // Win32 makes no guarantees about the order of sub keys, so sort to ensure1580  // reproducibility.1581  llvm::sort(Values);1582 1583  return detail::getHostCPUNameForARM(PrimaryCpuInfo, Values);1584}1585 1586#elif defined(__APPLE__) && defined(__powerpc__)1587StringRef sys::getHostCPUName() {1588  host_basic_info_data_t hostInfo;1589  mach_msg_type_number_t infoCount;1590 1591  infoCount = HOST_BASIC_INFO_COUNT;1592  mach_port_t hostPort = mach_host_self();1593  host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,1594            &infoCount);1595  mach_port_deallocate(mach_task_self(), hostPort);1596 1597  if (hostInfo.cpu_type != CPU_TYPE_POWERPC)1598    return "generic";1599 1600  switch (hostInfo.cpu_subtype) {1601  case CPU_SUBTYPE_POWERPC_601:1602    return "601";1603  case CPU_SUBTYPE_POWERPC_602:1604    return "602";1605  case CPU_SUBTYPE_POWERPC_603:1606    return "603";1607  case CPU_SUBTYPE_POWERPC_603e:1608    return "603e";1609  case CPU_SUBTYPE_POWERPC_603ev:1610    return "603ev";1611  case CPU_SUBTYPE_POWERPC_604:1612    return "604";1613  case CPU_SUBTYPE_POWERPC_604e:1614    return "604e";1615  case CPU_SUBTYPE_POWERPC_620:1616    return "620";1617  case CPU_SUBTYPE_POWERPC_750:1618    return "750";1619  case CPU_SUBTYPE_POWERPC_7400:1620    return "7400";1621  case CPU_SUBTYPE_POWERPC_7450:1622    return "7450";1623  case CPU_SUBTYPE_POWERPC_970:1624    return "970";1625  default:;1626  }1627 1628  return "generic";1629}1630#elif defined(__linux__) && defined(__powerpc__)1631StringRef sys::getHostCPUName() {1632  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1633  StringRef Content = P ? P->getBuffer() : "";1634  return detail::getHostCPUNameForPowerPC(Content);1635}1636#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))1637StringRef sys::getHostCPUName() {1638  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1639  StringRef Content = P ? P->getBuffer() : "";1640  return detail::getHostCPUNameForARM(Content);1641}1642#elif defined(__linux__) && defined(__s390x__)1643StringRef sys::getHostCPUName() {1644  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1645  StringRef Content = P ? P->getBuffer() : "";1646  return detail::getHostCPUNameForS390x(Content);1647}1648#elif defined(__MVS__)1649StringRef sys::getHostCPUName() {1650  // Get pointer to Communications Vector Table (CVT).1651  // The pointer is located at offset 16 of the Prefixed Save Area (PSA).1652  // It is stored as 31 bit pointer and will be zero-extended to 64 bit.1653  int *StartToCVTOffset = reinterpret_cast<int *>(0x10);1654  // Since its stored as a 31-bit pointer, get the 4 bytes from the start1655  // of address.1656  int ReadValue = *StartToCVTOffset;1657  // Explicitly clear the high order bit.1658  ReadValue = (ReadValue & 0x7FFFFFFF);1659  char *CVT = reinterpret_cast<char *>(ReadValue);1660  // The model number is located in the CVT prefix at offset -6 and stored as1661  // signless packed decimal.1662  uint16_t Id = *(uint16_t *)&CVT[-6];1663  // Convert number to integer.1664  Id = decodePackedBCD<uint16_t>(Id, false);1665  // Check for vector support. It's stored in field CVTFLAG5 (offset 244),1666  // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector1667  // extension can only be used if bit CVTVEF is on.1668  bool HaveVectorSupport = CVT[244] & 0x80;1669  return getCPUNameFromS390Model(Id, HaveVectorSupport);1670}1671#elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))1672// Copied from <mach/machine.h> in the macOS SDK.1673//1674// Also available here, though usually not as up-to-date:1675// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.41.3/osfmk/mach/machine.h#L403-L452.1676#define CPUFAMILY_UNKNOWN 01677#define CPUFAMILY_ARM_9 0xe73283ae1678#define CPUFAMILY_ARM_11 0x8ff620d81679#define CPUFAMILY_ARM_XSCALE 0x53b005f51680#define CPUFAMILY_ARM_12 0xbd1b0ae91681#define CPUFAMILY_ARM_13 0x0cc90e641682#define CPUFAMILY_ARM_14 0x96077ef11683#define CPUFAMILY_ARM_15 0xa8511bca1684#define CPUFAMILY_ARM_SWIFT 0x1e2d63811685#define CPUFAMILY_ARM_CYCLONE 0x37a096421686#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e1687#define CPUFAMILY_ARM_TWISTER 0x92fb37c81688#define CPUFAMILY_ARM_HURRICANE 0x67ceee931689#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef61690#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f1691#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d21692#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb31693#define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d1694#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea1695#define CPUFAMILY_ARM_IBIZA 0xfa33415e1696#define CPUFAMILY_ARM_PALMA 0x720158321697#define CPUFAMILY_ARM_COLL 0x2876f5b51698#define CPUFAMILY_ARM_LOBOS 0x5f4dea931699#define CPUFAMILY_ARM_DONAN 0x6f5129ac1700#define CPUFAMILY_ARM_BRAVA 0x17d5b93a1701#define CPUFAMILY_ARM_TAHITI 0x75d4acb91702#define CPUFAMILY_ARM_TUPAI 0x204526d01703 1704StringRef sys::getHostCPUName() {1705  uint32_t Family;1706  size_t Length = sizeof(Family);1707  sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);1708 1709  // This is found by testing on actual hardware, and by looking at:1710  // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.41.3/osfmk/arm/cpuid.c#L109-L231.1711  //1712  // Another great resource is1713  // https://github.com/AsahiLinux/docs/wiki/Codenames.1714  //1715  // NOTE: We choose to return `apple-mX` instead of `apple-aX`, since the M1,1716  // M2, M3 etc. aliases are more widely known to users than A14, A15, A16 etc.1717  // (and this code is basically only used on host macOS anyways).1718  switch (Family) {1719  case CPUFAMILY_UNKNOWN:1720    return "generic";1721  case CPUFAMILY_ARM_9:1722    return "arm920t"; // or arm926ej-s1723  case CPUFAMILY_ARM_11:1724    return "arm1136jf-s";1725  case CPUFAMILY_ARM_XSCALE:1726    return "xscale";1727  case CPUFAMILY_ARM_12: // Seems unused by the kernel1728    return "generic";1729  case CPUFAMILY_ARM_13:1730    return "cortex-a8";1731  case CPUFAMILY_ARM_14:1732    return "cortex-a9";1733  case CPUFAMILY_ARM_15:1734    return "cortex-a7";1735  case CPUFAMILY_ARM_SWIFT:1736    return "swift";1737  case CPUFAMILY_ARM_CYCLONE:1738    return "apple-a7";1739  case CPUFAMILY_ARM_TYPHOON:1740    return "apple-a8";1741  case CPUFAMILY_ARM_TWISTER:1742    return "apple-a9";1743  case CPUFAMILY_ARM_HURRICANE:1744    return "apple-a10";1745  case CPUFAMILY_ARM_MONSOON_MISTRAL:1746    return "apple-a11";1747  case CPUFAMILY_ARM_VORTEX_TEMPEST:1748    return "apple-a12";1749  case CPUFAMILY_ARM_LIGHTNING_THUNDER:1750    return "apple-a13";1751  case CPUFAMILY_ARM_FIRESTORM_ICESTORM: // A14 / M11752    return "apple-m1";1753  case CPUFAMILY_ARM_BLIZZARD_AVALANCHE: // A15 / M21754    return "apple-m2";1755  case CPUFAMILY_ARM_EVEREST_SAWTOOTH: // A161756  case CPUFAMILY_ARM_IBIZA:            // M31757  case CPUFAMILY_ARM_PALMA:            // M3 Max1758  case CPUFAMILY_ARM_LOBOS:            // M3 Pro1759    return "apple-m3";1760  case CPUFAMILY_ARM_COLL: // A17 Pro1761    return "apple-a17";1762  case CPUFAMILY_ARM_DONAN:  // M41763  case CPUFAMILY_ARM_BRAVA:  // M4 Max1764  case CPUFAMILY_ARM_TAHITI: // A18 Pro1765  case CPUFAMILY_ARM_TUPAI:  // A181766    return "apple-m4";1767  default:1768    // Default to the newest CPU we know about.1769    return "apple-m4";1770  }1771}1772#elif defined(_AIX)1773StringRef sys::getHostCPUName() {1774  switch (_system_configuration.implementation) {1775  case POWER_4:1776    if (_system_configuration.version == PV_4_3)1777      return "970";1778    return "pwr4";1779  case POWER_5:1780    if (_system_configuration.version == PV_5)1781      return "pwr5";1782    return "pwr5x";1783  case POWER_6:1784    if (_system_configuration.version == PV_6_Compat)1785      return "pwr6";1786    return "pwr6x";1787  case POWER_7:1788    return "pwr7";1789  case POWER_8:1790    return "pwr8";1791  case POWER_9:1792    return "pwr9";1793// TODO: simplify this once the macro is available in all OS levels.1794#ifdef POWER_101795  case POWER_10:1796#else1797  case 0x40000:1798#endif1799    return "pwr10";1800#ifdef POWER_111801  case POWER_11:1802#else1803  case 0x80000:1804#endif1805    return "pwr11";1806  default:1807    return "generic";1808  }1809}1810#elif defined(__loongarch__)1811StringRef sys::getHostCPUName() {1812  // Use processor id to detect cpu name.1813  uint32_t processor_id;1814  __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));1815  // Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h.1816  switch (processor_id & 0xf000) {1817  case 0xc000: // Loongson 64bit, 4-issue1818    return "la464";1819  case 0xd000: // Loongson 64bit, 6-issue1820    return "la664";1821  // TODO: Others.1822  default:1823    break;1824  }1825  return "generic";1826}1827#elif defined(__riscv)1828#if defined(__linux__)1829// struct riscv_hwprobe1830struct RISCVHwProbe {1831  int64_t Key;1832  uint64_t Value;1833};1834#endif1835 1836StringRef sys::getHostCPUName() {1837#if defined(__linux__)1838  // Try the hwprobe way first.1839  RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_MVENDORID=*/0, 0},1840                       {/*RISCV_HWPROBE_KEY_MARCHID=*/1, 0},1841                       {/*RISCV_HWPROBE_KEY_MIMPID=*/2, 0}};1842  int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,1843                    /*pair_count=*/std::size(Query), /*cpu_count=*/0,1844                    /*cpus=*/0, /*flags=*/0);1845  if (Ret == 0) {1846    RISCV::CPUModel Model{static_cast<uint32_t>(Query[0].Value), Query[1].Value,1847                          Query[2].Value};1848    StringRef Name = RISCV::getCPUNameFromCPUModel(Model);1849    if (!Name.empty())1850      return Name;1851  }1852 1853  // Then try the cpuinfo way.1854  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1855  StringRef Content = P ? P->getBuffer() : "";1856  StringRef Name = detail::getHostCPUNameForRISCV(Content);1857  if (!Name.empty())1858    return Name;1859#endif1860#if __riscv_xlen == 641861  return "generic-rv64";1862#elif __riscv_xlen == 321863  return "generic-rv32";1864#else1865#error "Unhandled value of __riscv_xlen"1866#endif1867}1868#elif defined(__sparc__)1869#if defined(__linux__)1870StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {1871  SmallVector<StringRef> Lines;1872  ProcCpuinfoContent.split(Lines, '\n');1873 1874  // Look for cpu line to determine cpu name1875  StringRef Cpu;1876  for (unsigned I = 0, E = Lines.size(); I != E; ++I) {1877    if (Lines[I].starts_with("cpu")) {1878      Cpu = Lines[I].substr(5).ltrim("\t :");1879      break;1880    }1881  }1882 1883  return StringSwitch<const char *>(Cpu)1884      .StartsWith("SuperSparc", "supersparc")1885      .StartsWith("HyperSparc", "hypersparc")1886      .StartsWith("SpitFire", "ultrasparc")1887      .StartsWith("BlackBird", "ultrasparc")1888      .StartsWith("Sabre", " ultrasparc")1889      .StartsWith("Hummingbird", "ultrasparc")1890      .StartsWith("Cheetah", "ultrasparc3")1891      .StartsWith("Jalapeno", "ultrasparc3")1892      .StartsWith("Jaguar", "ultrasparc3")1893      .StartsWith("Panther", "ultrasparc3")1894      .StartsWith("Serrano", "ultrasparc3")1895      .StartsWith("UltraSparc T1", "niagara")1896      .StartsWith("UltraSparc T2", "niagara2")1897      .StartsWith("UltraSparc T3", "niagara3")1898      .StartsWith("UltraSparc T4", "niagara4")1899      .StartsWith("UltraSparc T5", "niagara4")1900      .StartsWith("LEON", "leon3")1901      // niagara7/m8 not supported by LLVM yet.1902      .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)1903      .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)1904      .StartsWith("SPARC-M8", "niagara4" /* "m8" */)1905      .Default("generic");1906}1907#endif1908 1909StringRef sys::getHostCPUName() {1910#if defined(__linux__)1911  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();1912  StringRef Content = P ? P->getBuffer() : "";1913  return detail::getHostCPUNameForSPARC(Content);1914#elif defined(__sun__) && defined(__svr4__)1915  char *buf = NULL;1916  kstat_ctl_t *kc;1917  kstat_t *ksp;1918  kstat_named_t *brand = NULL;1919 1920  kc = kstat_open();1921  if (kc != NULL) {1922    ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);1923    if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&1924        ksp->ks_type == KSTAT_TYPE_NAMED)1925      brand =1926          (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));1927    if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)1928      buf = KSTAT_NAMED_STR_PTR(brand);1929  }1930  kstat_close(kc);1931 1932  return StringSwitch<const char *>(buf)1933      .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I1934      .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I1935      .Case("TMS390Z55",1936            "supersparc") // Texas Instruments SuperSPARC I with SuperCache1937      .Case("MB86904", "supersparc") // Fujitsu microSPARC II1938      .Case("MB86907", "supersparc") // Fujitsu TurboSPARC1939      .Case("RT623", "hypersparc")   // Ross hyperSPARC1940      .Case("RT625", "hypersparc")1941      .Case("RT626", "hypersparc")1942      .Case("UltraSPARC-I", "ultrasparc")1943      .Case("UltraSPARC-II", "ultrasparc")1944      .Case("UltraSPARC-IIe", "ultrasparc")1945      .Case("UltraSPARC-IIi", "ultrasparc")1946      .Case("SPARC64-III", "ultrasparc")1947      .Case("SPARC64-IV", "ultrasparc")1948      .Case("UltraSPARC-III", "ultrasparc3")1949      .Case("UltraSPARC-III+", "ultrasparc3")1950      .Case("UltraSPARC-IIIi", "ultrasparc3")1951      .Case("UltraSPARC-IIIi+", "ultrasparc3")1952      .Case("UltraSPARC-IV", "ultrasparc3")1953      .Case("UltraSPARC-IV+", "ultrasparc3")1954      .Case("SPARC64-V", "ultrasparc3")1955      .Case("SPARC64-VI", "ultrasparc3")1956      .Case("SPARC64-VII", "ultrasparc3")1957      .Case("UltraSPARC-T1", "niagara")1958      .Case("UltraSPARC-T2", "niagara2")1959      .Case("UltraSPARC-T2", "niagara2")1960      .Case("UltraSPARC-T2+", "niagara2")1961      .Case("SPARC-T3", "niagara3")1962      .Case("SPARC-T4", "niagara4")1963      .Case("SPARC-T5", "niagara4")1964      // niagara7/m8 not supported by LLVM yet.1965      .Case("SPARC-M7", "niagara4" /* "niagara7" */)1966      .Case("SPARC-S7", "niagara4" /* "niagara7" */)1967      .Case("SPARC-M8", "niagara4" /* "m8" */)1968      .Default("generic");1969#else1970  return "generic";1971#endif1972}1973#else1974StringRef sys::getHostCPUName() { return "generic"; }1975namespace llvm {1976namespace sys {1977namespace detail {1978namespace x86 {1979 1980VendorSignatures getVendorSignature(unsigned *MaxLeaf) {1981  return VendorSignatures::UNKNOWN;1982}1983 1984} // namespace x861985} // namespace detail1986} // namespace sys1987} // namespace llvm1988#endif1989 1990#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) ||           \1991     defined(_M_X64)) &&                                                       \1992    !defined(_M_ARM64EC)1993StringMap<bool> sys::getHostCPUFeatures() {1994  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;1995  unsigned MaxLevel;1996  StringMap<bool> Features;1997 1998  if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)1999    return Features;2000 2001  getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);2002 2003  Features["cx8"]    = (EDX >>  8) & 1;2004  Features["cmov"]   = (EDX >> 15) & 1;2005  Features["mmx"]    = (EDX >> 23) & 1;2006  Features["fxsr"]   = (EDX >> 24) & 1;2007  Features["sse"]    = (EDX >> 25) & 1;2008  Features["sse2"]   = (EDX >> 26) & 1;2009 2010  Features["sse3"]   = (ECX >>  0) & 1;2011  Features["pclmul"] = (ECX >>  1) & 1;2012  Features["ssse3"]  = (ECX >>  9) & 1;2013  Features["cx16"]   = (ECX >> 13) & 1;2014  Features["sse4.1"] = (ECX >> 19) & 1;2015  Features["sse4.2"] = (ECX >> 20) & 1;2016  Features["crc32"]  = Features["sse4.2"];2017  Features["movbe"]  = (ECX >> 22) & 1;2018  Features["popcnt"] = (ECX >> 23) & 1;2019  Features["aes"]    = (ECX >> 25) & 1;2020  Features["rdrnd"]  = (ECX >> 30) & 1;2021 2022  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV2023  // indicates that the AVX registers will be saved and restored on context2024  // switch, then we have full AVX support.2025  bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);2026  bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);2027#if defined(__APPLE__)2028  // Darwin lazily saves the AVX512 context on first use: trust that the OS will2029  // save the AVX512 context if we use AVX512 instructions, even the bit is not2030  // set right now.2031  bool HasAVX512Save = true;2032#else2033  // AVX512 requires additional context to be saved by the OS.2034  bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);2035#endif2036  // AMX requires additional context to be saved by the OS.2037  const unsigned AMXBits = (1 << 17) | (1 << 18);2038  bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);2039 2040  Features["avx"]   = HasAVXSave;2041  Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;2042  // Only enable XSAVE if OS has enabled support for saving YMM state.2043  Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;2044  Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;2045 2046  unsigned MaxExtLevel;2047  getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);2048 2049  bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&2050                     !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);2051  Features["sahf"]   = HasExtLeaf1 && ((ECX >>  0) & 1);2052  Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);2053  Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);2054  Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);2055  Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;2056  Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);2057  Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;2058  Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);2059  Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);2060 2061  Features["64bit"]  = HasExtLeaf1 && ((EDX >> 29) & 1);2062 2063  // Miscellaneous memory related features, detected by2064  // using the 0x80000008 leaf of the CPUID instruction2065  bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&2066                     !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);2067  Features["clzero"]   = HasExtLeaf8 && ((EBX >> 0) & 1);2068  Features["rdpru"]    = HasExtLeaf8 && ((EBX >> 4) & 1);2069  Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);2070 2071  bool HasExtLeaf21 = MaxExtLevel >= 0x80000021 &&2072                      !getX86CpuIDAndInfo(0x80000021, &EAX, &EBX, &ECX, &EDX);2073  // AMD cpuid bit for prefetchi is different from Intel2074  Features["prefetchi"] = HasExtLeaf21 && ((EAX >> 20) & 1);2075 2076  bool HasLeaf7 =2077      MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);2078 2079  Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);2080  Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);2081  Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);2082  // AVX2 is only supported if we have the OS save support from AVX.2083  Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;2084  Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);2085  Features["invpcid"]    = HasLeaf7 && ((EBX >> 10) & 1);2086  Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);2087  // AVX512 is only supported if the OS supports the context save for it.2088  Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;2089  Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;2090  Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);2091  Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);2092  Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;2093  Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);2094  Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);2095  Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;2096  Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);2097  Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;2098  Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;2099 2100  Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;2101  Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);2102  Features["waitpkg"]         = HasLeaf7 && ((ECX >>  5) & 1);2103  Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;2104  Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);2105  Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);2106  Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;2107  Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;2108  Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;2109  Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;2110  Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;2111  Features["rdpid"]           = HasLeaf7 && ((ECX >> 22) & 1);2112  Features["kl"]              = HasLeaf7 && ((ECX >> 23) & 1); // key locker2113  Features["cldemote"]        = HasLeaf7 && ((ECX >> 25) & 1);2114  Features["movdiri"]         = HasLeaf7 && ((ECX >> 27) & 1);2115  Features["movdir64b"]       = HasLeaf7 && ((ECX >> 28) & 1);2116  Features["enqcmd"]          = HasLeaf7 && ((ECX >> 29) & 1);2117 2118  Features["uintr"]           = HasLeaf7 && ((EDX >> 5) & 1);2119  Features["avx512vp2intersect"] =2120      HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;2121  Features["serialize"]       = HasLeaf7 && ((EDX >> 14) & 1);2122  Features["tsxldtrk"]        = HasLeaf7 && ((EDX >> 16) & 1);2123  // There are two CPUID leafs which information associated with the pconfig2124  // instruction:2125  // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th2126  // bit of EDX), while the EAX=0x1b leaf returns information on the2127  // availability of specific pconfig leafs.2128  // The target feature here only refers to the the first of these two.2129  // Users might need to check for the availability of specific pconfig2130  // leaves using cpuid, since that information is ignored while2131  // detecting features using the "-march=native" flag.2132  // For more info, see X86 ISA docs.2133  Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);2134  Features["amx-bf16"]   = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;2135  Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;2136  Features["amx-tile"]   = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;2137  Features["amx-int8"]   = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;2138  // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't2139  // return all 0s for invalid subleaves so check the limit.2140  bool HasLeaf7Subleaf1 =2141      HasLeaf7 && EAX >= 1 &&2142      !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);2143  Features["sha512"]     = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);2144  Features["sm3"]        = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);2145  Features["sm4"]        = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);2146  Features["raoint"]     = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);2147  Features["avxvnni"]    = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;2148  Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;2149  Features["amx-fp16"]   = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;2150  Features["cmpccxadd"]  = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);2151  Features["hreset"]     = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);2152  Features["avxifma"]    = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;2153  Features["movrs"] = HasLeaf7Subleaf1 && ((EAX >> 31) & 1);2154  Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;2155  Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;2156  Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;2157  Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;2158  Features["prefetchi"] |= HasLeaf7Subleaf1 && ((EDX >> 14) & 1);2159  Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);2160  bool HasAVX10 = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);2161  bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);2162  Features["egpr"] = HasAPXF;2163  Features["push2pop2"] = HasAPXF;2164  Features["ppx"] = HasAPXF;2165  Features["ndd"] = HasAPXF;2166  Features["ccmp"] = HasAPXF;2167  Features["nf"] = HasAPXF;2168  Features["cf"] = HasAPXF;2169  Features["zu"] = HasAPXF;2170 2171  bool HasLeafD = MaxLevel >= 0xd &&2172                  !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);2173 2174  // Only enable XSAVE if OS has enabled support for saving YMM state.2175  Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;2176  Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;2177  Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;2178 2179  bool HasLeaf14 = MaxLevel >= 0x14 &&2180                  !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);2181 2182  Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);2183 2184  bool HasLeaf19 =2185      MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);2186  Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);2187 2188  bool HasLeaf1E = MaxLevel >= 0x1e &&2189                   !getX86CpuIDAndInfoEx(0x1e, 0x1, &EAX, &EBX, &ECX, &EDX);2190  Features["amx-fp8"] = HasLeaf1E && ((EAX >> 4) & 1) && HasAMXSave;2191  Features["amx-tf32"] = HasLeaf1E && ((EAX >> 6) & 1) && HasAMXSave;2192  Features["amx-avx512"] = HasLeaf1E && ((EAX >> 7) & 1) && HasAMXSave;2193  Features["amx-movrs"] = HasLeaf1E && ((EAX >> 8) & 1) && HasAMXSave;2194 2195  bool HasLeaf24 =2196      MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);2197 2198  int AVX10Ver = HasLeaf24 && (EBX & 0xff);2199  Features["avx10.1"] = HasAVX10 && AVX10Ver >= 1;2200  Features["avx10.2"] = HasAVX10 && AVX10Ver >= 2;2201 2202  return Features;2203}2204#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))2205StringMap<bool> sys::getHostCPUFeatures() {2206  StringMap<bool> Features;2207  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();2208  if (!P)2209    return Features;2210 2211  SmallVector<StringRef, 32> Lines;2212  P->getBuffer().split(Lines, '\n');2213 2214  SmallVector<StringRef, 32> CPUFeatures;2215 2216  // Look for the CPU features.2217  for (unsigned I = 0, E = Lines.size(); I != E; ++I)2218    if (Lines[I].starts_with("Features")) {2219      Lines[I].split(CPUFeatures, ' ');2220      break;2221    }2222 2223#if defined(__aarch64__)2224  // All of these are "crypto" features, but we must sift out actual features2225  // as the former meaning of "crypto" as a single feature is no more.2226  enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };2227  uint32_t crypto = 0;2228#endif2229 2230  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {2231    StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])2232#if defined(__aarch64__)2233                                   .Case("asimd", "neon")2234                                   .Case("fp", "fp-armv8")2235                                   .Case("crc32", "crc")2236                                   .Case("atomics", "lse")2237                                   .Case("sha3", "sha3")2238                                   .Case("sm4", "sm4")2239                                   .Case("sve", "sve")2240                                   .Case("sve2", "sve2")2241                                   .Case("sveaes", "sve-aes")2242                                   .Case("svesha3", "sve-sha3")2243                                   .Case("svesm4", "sve-sm4")2244#else2245                                   .Case("half", "fp16")2246                                   .Case("neon", "neon")2247                                   .Case("vfpv3", "vfp3")2248                                   .Case("vfpv3d16", "vfp3d16")2249                                   .Case("vfpv4", "vfp4")2250                                   .Case("idiva", "hwdiv-arm")2251                                   .Case("idivt", "hwdiv")2252#endif2253                                   .Default("");2254 2255#if defined(__aarch64__)2256    // We need to check crypto separately since we need all of the crypto2257    // extensions to enable the subtarget feature2258    if (CPUFeatures[I] == "aes")2259      crypto |= CAP_AES;2260    else if (CPUFeatures[I] == "pmull")2261      crypto |= CAP_PMULL;2262    else if (CPUFeatures[I] == "sha1")2263      crypto |= CAP_SHA1;2264    else if (CPUFeatures[I] == "sha2")2265      crypto |= CAP_SHA2;2266#endif2267 2268    if (LLVMFeatureStr != "")2269      Features[LLVMFeatureStr] = true;2270  }2271 2272#if defined(__aarch64__)2273  // LLVM has decided some AArch64 CPUs have all the instructions they _may_2274  // have, as opposed to all the instructions they _must_ have, so allow runtime2275  // information to correct us on that.2276  uint32_t Aes = CAP_AES | CAP_PMULL;2277  uint32_t Sha2 = CAP_SHA1 | CAP_SHA2;2278  Features["aes"] = (crypto & Aes) == Aes;2279  Features["sha2"] = (crypto & Sha2) == Sha2;2280 2281  // Even if an underlying core supports SVE, it might not be available if2282  // it's disabled by the OS, or some other layer. Disable SVE if we don't2283  // detect support at runtime.2284  if (!Features.contains("sve"))2285    Features["sve"] = false;2286#endif2287 2288  return Features;2289}2290#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64) ||         \2291                          defined(__arm64ec__) || defined(_M_ARM64EC))2292#ifndef PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE2293#define PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 432294#endif2295#ifndef PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE2296#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE 442297#endif2298#ifndef PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE2299#define PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE 452300#endif2301#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE2302#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE 462303#endif2304#ifndef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE2305#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE 472306#endif2307#ifndef PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE2308#define PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE 502309#endif2310#ifndef PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE2311#define PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE 552312#endif2313#ifndef PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE2314#define PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE 562315#endif2316#ifndef PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE2317#define PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE 572318#endif2319#ifndef PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE2320#define PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE 582321#endif2322#ifndef PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE2323#define PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE 592324#endif2325StringMap<bool> sys::getHostCPUFeatures() {2326  StringMap<bool> Features;2327 2328  // If we're asking the OS at runtime, believe what the OS says2329  Features["crc"] =2330      IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);2331  Features["lse"] =2332      IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE);2333  Features["dotprod"] =2334      IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE);2335  Features["jsconv"] =2336      IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE);2337  Features["rcpc"] =2338      IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE);2339  Features["sve"] =2340      IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE);2341  Features["sve2"] =2342      IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE);2343  Features["sve-aes"] =2344      IsProcessorFeaturePresent(PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE);2345  Features["sve-sha3"] =2346      IsProcessorFeaturePresent(PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE);2347  Features["sve-sm4"] =2348      IsProcessorFeaturePresent(PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE);2349  Features["f32mm"] =2350      IsProcessorFeaturePresent(PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE);2351  Features["f64mm"] =2352      IsProcessorFeaturePresent(PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE);2353  Features["i8mm"] =2354      IsProcessorFeaturePresent(PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE);2355 2356  // Avoid inferring "crypto" means more than the traditional AES + SHA22357  bool TradCrypto =2358      IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);2359  Features["aes"] = TradCrypto;2360  Features["sha2"] = TradCrypto;2361 2362  return Features;2363}2364#elif defined(__linux__) && defined(__loongarch__)2365#include <sys/auxv.h>2366StringMap<bool> sys::getHostCPUFeatures() {2367  unsigned long hwcap = getauxval(AT_HWCAP);2368  bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU2369  uint32_t cpucfg2 = 0x2, cpucfg3 = 0x3;2370  __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));2371  __asm__("cpucfg %[cpucfg3], %[cpucfg3]\n\t" : [cpucfg3] "+r"(cpucfg3));2372 2373  StringMap<bool> Features;2374 2375  Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP2376  Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP2377 2378  Features["lsx"] = hwcap & (1UL << 4);  // HWCAP_LOONGARCH_LSX2379  Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX2380  Features["lvz"] = hwcap & (1UL << 9);  // HWCAP_LOONGARCH_LVZ2381 2382  Features["frecipe"] = cpucfg2 & (1U << 25); // CPUCFG.2.FRECIPE2383  Features["div32"] = cpucfg2 & (1U << 26);   // CPUCFG.2.DIV322384  Features["lam-bh"] = cpucfg2 & (1U << 27);  // CPUCFG.2.LAM_BH2385  Features["lamcas"] = cpucfg2 & (1U << 28);  // CPUCFG.2.LAMCAS2386  Features["scq"] = cpucfg2 & (1U << 30);     // CPUCFG.2.SCQ2387 2388  Features["ld-seq-sa"] = cpucfg3 & (1U << 23); // CPUCFG.3.LD_SEQ_SA2389 2390  // TODO: Need to complete.2391  // Features["llacq-screl"] = cpucfg2 & (1U << 29); // CPUCFG.2.LLACQ_SCREL2392  return Features;2393}2394#elif defined(__linux__) && defined(__riscv)2395StringMap<bool> sys::getHostCPUFeatures() {2396  RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0},2397                       {/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0},2398                       {/*RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF=*/9, 0}};2399  int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,2400                    /*pair_count=*/std::size(Query), /*cpu_count=*/0,2401                    /*cpus=*/0, /*flags=*/0);2402  if (Ret != 0)2403    return {};2404 2405  StringMap<bool> Features;2406  uint64_t BaseMask = Query[0].Value;2407  // Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set.2408  if (BaseMask & 1) {2409    Features["i"] = true;2410    Features["m"] = true;2411    Features["a"] = true;2412  }2413 2414  uint64_t ExtMask = Query[1].Value;2415  Features["f"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD2416  Features["d"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD2417  Features["c"] = ExtMask & (1 << 1);           // RISCV_HWPROBE_IMA_C2418  Features["v"] = ExtMask & (1 << 2);           // RISCV_HWPROBE_IMA_V2419  Features["zba"] = ExtMask & (1 << 3);         // RISCV_HWPROBE_EXT_ZBA2420  Features["zbb"] = ExtMask & (1 << 4);         // RISCV_HWPROBE_EXT_ZBB2421  Features["zbs"] = ExtMask & (1 << 5);         // RISCV_HWPROBE_EXT_ZBS2422  Features["zicboz"] = ExtMask & (1 << 6);      // RISCV_HWPROBE_EXT_ZICBOZ2423  Features["zbc"] = ExtMask & (1 << 7);         // RISCV_HWPROBE_EXT_ZBC2424  Features["zbkb"] = ExtMask & (1 << 8);        // RISCV_HWPROBE_EXT_ZBKB2425  Features["zbkc"] = ExtMask & (1 << 9);        // RISCV_HWPROBE_EXT_ZBKC2426  Features["zbkx"] = ExtMask & (1 << 10);       // RISCV_HWPROBE_EXT_ZBKX2427  Features["zknd"] = ExtMask & (1 << 11);       // RISCV_HWPROBE_EXT_ZKND2428  Features["zkne"] = ExtMask & (1 << 12);       // RISCV_HWPROBE_EXT_ZKNE2429  Features["zknh"] = ExtMask & (1 << 13);       // RISCV_HWPROBE_EXT_ZKNH2430  Features["zksed"] = ExtMask & (1 << 14);      // RISCV_HWPROBE_EXT_ZKSED2431  Features["zksh"] = ExtMask & (1 << 15);       // RISCV_HWPROBE_EXT_ZKSH2432  Features["zkt"] = ExtMask & (1 << 16);        // RISCV_HWPROBE_EXT_ZKT2433  Features["zvbb"] = ExtMask & (1 << 17);       // RISCV_HWPROBE_EXT_ZVBB2434  Features["zvbc"] = ExtMask & (1 << 18);       // RISCV_HWPROBE_EXT_ZVBC2435  Features["zvkb"] = ExtMask & (1 << 19);       // RISCV_HWPROBE_EXT_ZVKB2436  Features["zvkg"] = ExtMask & (1 << 20);       // RISCV_HWPROBE_EXT_ZVKG2437  Features["zvkned"] = ExtMask & (1 << 21);     // RISCV_HWPROBE_EXT_ZVKNED2438  Features["zvknha"] = ExtMask & (1 << 22);     // RISCV_HWPROBE_EXT_ZVKNHA2439  Features["zvknhb"] = ExtMask & (1 << 23);     // RISCV_HWPROBE_EXT_ZVKNHB2440  Features["zvksed"] = ExtMask & (1 << 24);     // RISCV_HWPROBE_EXT_ZVKSED2441  Features["zvksh"] = ExtMask & (1 << 25);      // RISCV_HWPROBE_EXT_ZVKSH2442  Features["zvkt"] = ExtMask & (1 << 26);       // RISCV_HWPROBE_EXT_ZVKT2443  Features["zfh"] = ExtMask & (1 << 27);        // RISCV_HWPROBE_EXT_ZFH2444  Features["zfhmin"] = ExtMask & (1 << 28);     // RISCV_HWPROBE_EXT_ZFHMIN2445  Features["zihintntl"] = ExtMask & (1 << 29);  // RISCV_HWPROBE_EXT_ZIHINTNTL2446  Features["zvfh"] = ExtMask & (1 << 30);       // RISCV_HWPROBE_EXT_ZVFH2447  Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN2448  Features["zfa"] = ExtMask & (1ULL << 32);     // RISCV_HWPROBE_EXT_ZFA2449  Features["ztso"] = ExtMask & (1ULL << 33);    // RISCV_HWPROBE_EXT_ZTSO2450  Features["zacas"] = ExtMask & (1ULL << 34);   // RISCV_HWPROBE_EXT_ZACAS2451  Features["zicond"] = ExtMask & (1ULL << 35);  // RISCV_HWPROBE_EXT_ZICOND2452  Features["zihintpause"] =2453      ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE2454  Features["zve32x"] = ExtMask & (1ULL << 37); // RISCV_HWPROBE_EXT_ZVE32X2455  Features["zve32f"] = ExtMask & (1ULL << 38); // RISCV_HWPROBE_EXT_ZVE32F2456  Features["zve64x"] = ExtMask & (1ULL << 39); // RISCV_HWPROBE_EXT_ZVE64X2457  Features["zve64f"] = ExtMask & (1ULL << 40); // RISCV_HWPROBE_EXT_ZVE64F2458  Features["zve64d"] = ExtMask & (1ULL << 41); // RISCV_HWPROBE_EXT_ZVE64D2459  Features["zimop"] = ExtMask & (1ULL << 42);  // RISCV_HWPROBE_EXT_ZIMOP2460  Features["zca"] = ExtMask & (1ULL << 43);    // RISCV_HWPROBE_EXT_ZCA2461  Features["zcb"] = ExtMask & (1ULL << 44);    // RISCV_HWPROBE_EXT_ZCB2462  Features["zcd"] = ExtMask & (1ULL << 45);    // RISCV_HWPROBE_EXT_ZCD2463  Features["zcf"] = ExtMask & (1ULL << 46);    // RISCV_HWPROBE_EXT_ZCF2464  Features["zcmop"] = ExtMask & (1ULL << 47);  // RISCV_HWPROBE_EXT_ZCMOP2465  Features["zawrs"] = ExtMask & (1ULL << 48);  // RISCV_HWPROBE_EXT_ZAWRS2466 2467  // Check whether the processor supports fast misaligned scalar memory access.2468  // NOTE: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF is only available on2469  // Linux 6.11 or later. If it is not recognized, the key field will be cleared2470  // to -1.2471  if (Query[2].Key != -1 &&2472      Query[2].Value == /*RISCV_HWPROBE_MISALIGNED_SCALAR_FAST=*/3)2473    Features["unaligned-scalar-mem"] = true;2474 2475  return Features;2476}2477#else2478StringMap<bool> sys::getHostCPUFeatures() { return {}; }2479#endif2480 2481#if __APPLE__2482/// \returns the \p triple, but with the Host's arch spliced in.2483static Triple withHostArch(Triple T) {2484#if defined(__arm__)2485  T.setArch(Triple::arm);2486  T.setArchName("arm");2487#elif defined(__arm64e__)2488  T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);2489  T.setArchName("arm64e");2490#elif defined(__aarch64__)2491  T.setArch(Triple::aarch64);2492  T.setArchName("arm64");2493#elif defined(__x86_64h__)2494  T.setArch(Triple::x86_64);2495  T.setArchName("x86_64h");2496#elif defined(__x86_64__)2497  T.setArch(Triple::x86_64);2498  T.setArchName("x86_64");2499#elif defined(__i386__)2500  T.setArch(Triple::x86);2501  T.setArchName("i386");2502#elif defined(__powerpc__)2503  T.setArch(Triple::ppc);2504  T.setArchName("powerpc");2505#else2506#  error "Unimplemented host arch fixup"2507#endif2508  return T;2509}2510#endif2511 2512std::string sys::getProcessTriple() {2513  std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);2514  Triple PT(Triple::normalize(TargetTripleString));2515 2516#if __APPLE__2517  /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of2518  /// the slices. This fixes that up.2519  PT = withHostArch(PT);2520#endif2521 2522  if (sizeof(void *) == 8 && PT.isArch32Bit())2523    PT = PT.get64BitArchVariant();2524  if (sizeof(void *) == 4 && PT.isArch64Bit())2525    PT = PT.get32BitArchVariant();2526 2527  return PT.str();2528}2529 2530void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {2531#if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO2532  std::string CPU = std::string(sys::getHostCPUName());2533  if (CPU == "generic")2534    CPU = "(unknown)";2535  OS << "  Default target: " << sys::getDefaultTargetTriple() << '\n'2536     << "  Host CPU: " << CPU << '\n';2537#endif2538}2539