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