Host.cpp revision 327952
1218885Sdim//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10276479Sdim//  This file implements the operating system Host concept.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14249423Sdim#include "llvm/Support/Host.h"
15327952Sdim#include "llvm/Support/TargetParser.h"
16314564Sdim#include "llvm/ADT/SmallSet.h"
17239462Sdim#include "llvm/ADT/SmallVector.h"
18239462Sdim#include "llvm/ADT/StringRef.h"
19239462Sdim#include "llvm/ADT/StringSwitch.h"
20249423Sdim#include "llvm/ADT/Triple.h"
21249423Sdim#include "llvm/Config/config.h"
22239462Sdim#include "llvm/Support/Debug.h"
23280031Sdim#include "llvm/Support/FileSystem.h"
24314564Sdim#include "llvm/Support/MemoryBuffer.h"
25239462Sdim#include "llvm/Support/raw_ostream.h"
26314564Sdim#include <assert.h>
27218885Sdim#include <string.h>
28218885Sdim
29218885Sdim// Include the platform-specific parts of this class.
30218885Sdim#ifdef LLVM_ON_UNIX
31218885Sdim#include "Unix/Host.inc"
32218885Sdim#endif
33218885Sdim#ifdef LLVM_ON_WIN32
34218885Sdim#include "Windows/Host.inc"
35218885Sdim#endif
36218885Sdim#ifdef _MSC_VER
37218885Sdim#include <intrin.h>
38218885Sdim#endif
39239462Sdim#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
40309124Sdim#include <mach/host_info.h>
41239462Sdim#include <mach/mach.h>
42239462Sdim#include <mach/mach_host.h>
43239462Sdim#include <mach/machine.h>
44239462Sdim#endif
45218885Sdim
46276479Sdim#define DEBUG_TYPE "host-detection"
47276479Sdim
48218885Sdim//===----------------------------------------------------------------------===//
49218885Sdim//
50218885Sdim//  Implementations of the CPU detection routines
51218885Sdim//
52218885Sdim//===----------------------------------------------------------------------===//
53218885Sdim
54218885Sdimusing namespace llvm;
55218885Sdim
56321369Sdimstatic std::unique_ptr<llvm::MemoryBuffer>
57321369Sdim    LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
58321369Sdim  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
59321369Sdim      llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
60321369Sdim  if (std::error_code EC = Text.getError()) {
61321369Sdim    llvm::errs() << "Can't read "
62321369Sdim                 << "/proc/cpuinfo: " << EC.message() << "\n";
63321369Sdim    return nullptr;
64321369Sdim  }
65321369Sdim  return std::move(*Text);
66321369Sdim}
67280031Sdim
68321369SdimStringRef sys::detail::getHostCPUNameForPowerPC(
69321369Sdim    const StringRef &ProcCpuinfoContent) {
70321369Sdim  // Access to the Processor Version Register (PVR) on PowerPC is privileged,
71321369Sdim  // and so we must use an operating-system interface to determine the current
72321369Sdim  // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
73321369Sdim  const char *generic = "generic";
74321369Sdim
75321369Sdim  // The cpu line is second (after the 'processor: 0' line), so if this
76321369Sdim  // buffer is too small then something has changed (or is wrong).
77321369Sdim  StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
78321369Sdim  StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
79321369Sdim
80321369Sdim  StringRef::const_iterator CIP = CPUInfoStart;
81321369Sdim
82321369Sdim  StringRef::const_iterator CPUStart = 0;
83321369Sdim  size_t CPULen = 0;
84321369Sdim
85321369Sdim  // We need to find the first line which starts with cpu, spaces, and a colon.
86321369Sdim  // After the colon, there may be some additional spaces and then the cpu type.
87321369Sdim  while (CIP < CPUInfoEnd && CPUStart == 0) {
88321369Sdim    if (CIP < CPUInfoEnd && *CIP == '\n')
89321369Sdim      ++CIP;
90321369Sdim
91321369Sdim    if (CIP < CPUInfoEnd && *CIP == 'c') {
92321369Sdim      ++CIP;
93321369Sdim      if (CIP < CPUInfoEnd && *CIP == 'p') {
94321369Sdim        ++CIP;
95321369Sdim        if (CIP < CPUInfoEnd && *CIP == 'u') {
96321369Sdim          ++CIP;
97321369Sdim          while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
98321369Sdim            ++CIP;
99321369Sdim
100321369Sdim          if (CIP < CPUInfoEnd && *CIP == ':') {
101321369Sdim            ++CIP;
102321369Sdim            while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
103321369Sdim              ++CIP;
104321369Sdim
105321369Sdim            if (CIP < CPUInfoEnd) {
106321369Sdim              CPUStart = CIP;
107321369Sdim              while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
108321369Sdim                                          *CIP != ',' && *CIP != '\n'))
109321369Sdim                ++CIP;
110321369Sdim              CPULen = CIP - CPUStart;
111321369Sdim            }
112321369Sdim          }
113321369Sdim        }
114321369Sdim      }
115321369Sdim    }
116321369Sdim
117321369Sdim    if (CPUStart == 0)
118321369Sdim      while (CIP < CPUInfoEnd && *CIP != '\n')
119321369Sdim        ++CIP;
120280031Sdim  }
121321369Sdim
122321369Sdim  if (CPUStart == 0)
123321369Sdim    return generic;
124321369Sdim
125321369Sdim  return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
126321369Sdim      .Case("604e", "604e")
127321369Sdim      .Case("604", "604")
128321369Sdim      .Case("7400", "7400")
129321369Sdim      .Case("7410", "7400")
130321369Sdim      .Case("7447", "7400")
131321369Sdim      .Case("7455", "7450")
132321369Sdim      .Case("G4", "g4")
133321369Sdim      .Case("POWER4", "970")
134321369Sdim      .Case("PPC970FX", "970")
135321369Sdim      .Case("PPC970MP", "970")
136321369Sdim      .Case("G5", "g5")
137321369Sdim      .Case("POWER5", "g5")
138321369Sdim      .Case("A2", "a2")
139321369Sdim      .Case("POWER6", "pwr6")
140321369Sdim      .Case("POWER7", "pwr7")
141321369Sdim      .Case("POWER8", "pwr8")
142321369Sdim      .Case("POWER8E", "pwr8")
143321369Sdim      .Case("POWER8NVL", "pwr8")
144321369Sdim      .Case("POWER9", "pwr9")
145321369Sdim      .Default(generic);
146280031Sdim}
147280031Sdim
148321369SdimStringRef sys::detail::getHostCPUNameForARM(
149321369Sdim    const 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")
198321369Sdim            .Default("generic");
199321369Sdim  }
200321369Sdim
201321369Sdim  if (Implementer == "0x51") // Qualcomm Technologies, Inc.
202321369Sdim    // Look for the CPU part line.
203321369Sdim    for (unsigned I = 0, E = Lines.size(); I != E; ++I)
204321369Sdim      if (Lines[I].startswith("CPU part"))
205321369Sdim        // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
206321369Sdim        // values correspond to the "Part number" in the CP15/c0 register. The
207321369Sdim        // contents are specified in the various processor manuals.
208321369Sdim        return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
209321369Sdim            .Case("0x06f", "krait") // APQ8064
210321369Sdim            .Case("0x201", "kryo")
211321369Sdim            .Case("0x205", "kryo")
212327952Sdim            .Case("0x211", "kryo")
213327952Sdim            .Case("0x800", "cortex-a73")
214327952Sdim            .Case("0x801", "cortex-a73")
215326496Sdim            .Case("0xc00", "falkor")
216327952Sdim            .Case("0xc01", "saphira")
217321369Sdim            .Default("generic");
218321369Sdim
219327952Sdim  if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
220327952Sdim    // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
221327952Sdim    // any predictive pattern across variants and parts.
222327952Sdim    unsigned Variant = 0, Part = 0;
223327952Sdim
224327952Sdim    // Look for the CPU variant line, whose value is a 1 digit hexadecimal
225327952Sdim    // number, corresponding to the Variant bits in the CP15/C0 register.
226327952Sdim    for (auto I : Lines)
227327952Sdim      if (I.consume_front("CPU variant"))
228327952Sdim        I.ltrim("\t :").getAsInteger(0, Variant);
229327952Sdim
230327952Sdim    // Look for the CPU part line, whose value is a 3 digit hexadecimal
231327952Sdim    // number, corresponding to the PartNum bits in the CP15/C0 register.
232327952Sdim    for (auto I : Lines)
233327952Sdim      if (I.consume_front("CPU part"))
234327952Sdim        I.ltrim("\t :").getAsInteger(0, Part);
235327952Sdim
236327952Sdim    unsigned Exynos = (Variant << 12) | Part;
237327952Sdim    switch (Exynos) {
238327952Sdim    default:
239327952Sdim      // Default by falling through to Exynos M1.
240327952Sdim      LLVM_FALLTHROUGH;
241327952Sdim
242327952Sdim    case 0x1001:
243327952Sdim      return "exynos-m1";
244327952Sdim
245327952Sdim    case 0x4001:
246327952Sdim      return "exynos-m2";
247327952Sdim    }
248327952Sdim  }
249327952Sdim
250321369Sdim  return "generic";
251321369Sdim}
252321369Sdim
253321369SdimStringRef sys::detail::getHostCPUNameForS390x(
254321369Sdim    const StringRef &ProcCpuinfoContent) {
255321369Sdim  // STIDP is a privileged operation, so use /proc/cpuinfo instead.
256321369Sdim
257321369Sdim  // The "processor 0:" line comes after a fair amount of other information,
258321369Sdim  // including a cache breakdown, but this should be plenty.
259321369Sdim  SmallVector<StringRef, 32> Lines;
260321369Sdim  ProcCpuinfoContent.split(Lines, "\n");
261321369Sdim
262321369Sdim  // Look for the CPU features.
263321369Sdim  SmallVector<StringRef, 32> CPUFeatures;
264321369Sdim  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
265321369Sdim    if (Lines[I].startswith("features")) {
266321369Sdim      size_t Pos = Lines[I].find(":");
267321369Sdim      if (Pos != StringRef::npos) {
268321369Sdim        Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
269321369Sdim        break;
270321369Sdim      }
271321369Sdim    }
272321369Sdim
273321369Sdim  // We need to check for the presence of vector support independently of
274321369Sdim  // the machine type, since we may only use the vector register set when
275321369Sdim  // supported by the kernel (and hypervisor).
276321369Sdim  bool HaveVectorSupport = false;
277321369Sdim  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
278321369Sdim    if (CPUFeatures[I] == "vx")
279321369Sdim      HaveVectorSupport = true;
280321369Sdim  }
281321369Sdim
282321369Sdim  // Now check the processor machine type.
283321369Sdim  for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
284321369Sdim    if (Lines[I].startswith("processor ")) {
285321369Sdim      size_t Pos = Lines[I].find("machine = ");
286321369Sdim      if (Pos != StringRef::npos) {
287321369Sdim        Pos += sizeof("machine = ") - 1;
288321369Sdim        unsigned int Id;
289321369Sdim        if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
290321369Sdim          if (Id >= 3906 && HaveVectorSupport)
291321369Sdim            return "z14";
292321369Sdim          if (Id >= 2964 && HaveVectorSupport)
293321369Sdim            return "z13";
294321369Sdim          if (Id >= 2827)
295321369Sdim            return "zEC12";
296321369Sdim          if (Id >= 2817)
297321369Sdim            return "z196";
298321369Sdim        }
299321369Sdim      }
300321369Sdim      break;
301321369Sdim    }
302321369Sdim  }
303321369Sdim
304321369Sdim  return "generic";
305321369Sdim}
306321369Sdim
307327952SdimStringRef sys::detail::getHostCPUNameForBPF() {
308327952Sdim#if !defined(__linux__) || !defined(__x86_64__)
309327952Sdim  return "generic";
310327952Sdim#else
311327952Sdim  uint8_t insns[40] __attribute__ ((aligned (8))) =
312327952Sdim      /* BPF_MOV64_IMM(BPF_REG_0, 0) */
313327952Sdim    { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
314327952Sdim      /* BPF_MOV64_IMM(BPF_REG_2, 1) */
315327952Sdim      0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
316327952Sdim      /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
317327952Sdim      0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
318327952Sdim      /* BPF_MOV64_IMM(BPF_REG_0, 1) */
319327952Sdim      0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
320327952Sdim      /* BPF_EXIT_INSN() */
321327952Sdim      0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
322327952Sdim
323327952Sdim  struct bpf_prog_load_attr {
324327952Sdim    uint32_t prog_type;
325327952Sdim    uint32_t insn_cnt;
326327952Sdim    uint64_t insns;
327327952Sdim    uint64_t license;
328327952Sdim    uint32_t log_level;
329327952Sdim    uint32_t log_size;
330327952Sdim    uint64_t log_buf;
331327952Sdim    uint32_t kern_version;
332327952Sdim    uint32_t prog_flags;
333327952Sdim  } attr = {};
334327952Sdim  attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
335327952Sdim  attr.insn_cnt = 5;
336327952Sdim  attr.insns = (uint64_t)insns;
337327952Sdim  attr.license = (uint64_t)"DUMMY";
338327952Sdim
339327952Sdim  int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
340327952Sdim  if (fd >= 0) {
341327952Sdim    close(fd);
342327952Sdim    return "v2";
343327952Sdim  }
344327952Sdim  return "v1";
345327952Sdim#endif
346327952Sdim}
347327952Sdim
348314564Sdim#if defined(__i386__) || defined(_M_IX86) || \
349314564Sdim    defined(__x86_64__) || defined(_M_X64)
350218885Sdim
351309124Sdimenum VendorSignatures {
352309124Sdim  SIG_INTEL = 0x756e6547 /* Genu */,
353309124Sdim  SIG_AMD = 0x68747541 /* Auth */
354309124Sdim};
355309124Sdim
356314564Sdim// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
357314564Sdim// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
358314564Sdim// support. Consequently, for i386, the presence of CPUID is checked first
359314564Sdim// via the corresponding eflags bit.
360314564Sdim// Removal of cpuid.h header motivated by PR30384
361314564Sdim// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
362314564Sdim// or test-suite, but are used in external projects e.g. libstdcxx
363314564Sdimstatic bool isCpuIdSupported() {
364314564Sdim#if defined(__GNUC__) || defined(__clang__)
365314564Sdim#if defined(__i386__)
366314564Sdim  int __cpuid_supported;
367314564Sdim  __asm__("  pushfl\n"
368314564Sdim          "  popl   %%eax\n"
369314564Sdim          "  movl   %%eax,%%ecx\n"
370314564Sdim          "  xorl   $0x00200000,%%eax\n"
371314564Sdim          "  pushl  %%eax\n"
372314564Sdim          "  popfl\n"
373314564Sdim          "  pushfl\n"
374314564Sdim          "  popl   %%eax\n"
375314564Sdim          "  movl   $0,%0\n"
376314564Sdim          "  cmpl   %%eax,%%ecx\n"
377314564Sdim          "  je     1f\n"
378314564Sdim          "  movl   $1,%0\n"
379314564Sdim          "1:"
380314564Sdim          : "=r"(__cpuid_supported)
381314564Sdim          :
382314564Sdim          : "eax", "ecx");
383314564Sdim  if (!__cpuid_supported)
384314564Sdim    return false;
385314564Sdim#endif
386314564Sdim  return true;
387314564Sdim#endif
388314564Sdim  return true;
389314564Sdim}
390314564Sdim
391309124Sdim/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
392309124Sdim/// the specified arguments.  If we can't run cpuid on the host, return true.
393309124Sdimstatic bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
394261991Sdim                               unsigned *rECX, unsigned *rEDX) {
395261991Sdim#if defined(__GNUC__) || defined(__clang__)
396314564Sdim#if defined(__x86_64__)
397314564Sdim  // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
398314564Sdim  // FIXME: should we save this for Clang?
399314564Sdim  __asm__("movq\t%%rbx, %%rsi\n\t"
400314564Sdim          "cpuid\n\t"
401314564Sdim          "xchgq\t%%rbx, %%rsi\n\t"
402314564Sdim          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
403314564Sdim          : "a"(value));
404321369Sdim  return false;
405314564Sdim#elif defined(__i386__)
406314564Sdim  __asm__("movl\t%%ebx, %%esi\n\t"
407314564Sdim          "cpuid\n\t"
408314564Sdim          "xchgl\t%%ebx, %%esi\n\t"
409314564Sdim          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
410314564Sdim          : "a"(value));
411321369Sdim  return false;
412309124Sdim#else
413321369Sdim  return true;
414309124Sdim#endif
415261991Sdim#elif defined(_MSC_VER)
416261991Sdim  // The MSVC intrinsic is portable across x86 and x64.
417261991Sdim  int registers[4];
418261991Sdim  __cpuid(registers, value);
419261991Sdim  *rEAX = registers[0];
420261991Sdim  *rEBX = registers[1];
421261991Sdim  *rECX = registers[2];
422261991Sdim  *rEDX = registers[3];
423261991Sdim  return false;
424261991Sdim#else
425261991Sdim  return true;
426261991Sdim#endif
427261991Sdim}
428261991Sdim
429309124Sdim/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
430309124Sdim/// the 4 values in the specified arguments.  If we can't run cpuid on the host,
431261991Sdim/// return true.
432309124Sdimstatic bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
433276479Sdim                                 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
434276479Sdim                                 unsigned *rEDX) {
435314564Sdim#if defined(__GNUC__) || defined(__clang__)
436321369Sdim#if defined(__x86_64__)
437321369Sdim  // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
438314564Sdim  // FIXME: should we save this for Clang?
439314564Sdim  __asm__("movq\t%%rbx, %%rsi\n\t"
440314564Sdim          "cpuid\n\t"
441314564Sdim          "xchgq\t%%rbx, %%rsi\n\t"
442314564Sdim          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
443314564Sdim          : "a"(value), "c"(subleaf));
444321369Sdim  return false;
445321369Sdim#elif defined(__i386__)
446321369Sdim  __asm__("movl\t%%ebx, %%esi\n\t"
447321369Sdim          "cpuid\n\t"
448321369Sdim          "xchgl\t%%ebx, %%esi\n\t"
449321369Sdim          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
450321369Sdim          : "a"(value), "c"(subleaf));
451321369Sdim  return false;
452321369Sdim#else
453321369Sdim  return true;
454321369Sdim#endif
455309124Sdim#elif defined(_MSC_VER)
456309124Sdim  int registers[4];
457309124Sdim  __cpuidex(registers, value, subleaf);
458309124Sdim  *rEAX = registers[0];
459309124Sdim  *rEBX = registers[1];
460309124Sdim  *rECX = registers[2];
461309124Sdim  *rEDX = registers[3];
462314564Sdim  return false;
463309124Sdim#else
464309124Sdim  return true;
465309124Sdim#endif
466218885Sdim}
467218885Sdim
468321369Sdim// Read control register 0 (XCR0). Used to detect features such as AVX.
469309124Sdimstatic bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
470314564Sdim#if defined(__GNUC__) || defined(__clang__)
471251662Sdim  // Check xgetbv; this uses a .byte sequence instead of the instruction
472251662Sdim  // directly because older assemblers do not include support for xgetbv and
473251662Sdim  // there is no easy way to conditionally compile based on the assembler used.
474309124Sdim  __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
475288943Sdim  return false;
476251662Sdim#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
477288943Sdim  unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
478288943Sdim  *rEAX = Result;
479288943Sdim  *rEDX = Result >> 32;
480288943Sdim  return false;
481251662Sdim#else
482288943Sdim  return true;
483251662Sdim#endif
484249423Sdim}
485249423Sdim
486309124Sdimstatic void detectX86FamilyModel(unsigned EAX, unsigned *Family,
487309124Sdim                                 unsigned *Model) {
488309124Sdim  *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
489309124Sdim  *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
490309124Sdim  if (*Family == 6 || *Family == 0xf) {
491309124Sdim    if (*Family == 0xf)
492218885Sdim      // Examine extended family ID if family ID is F.
493309124Sdim      *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
494218885Sdim    // Examine extended model ID if family ID is 6 or F.
495309124Sdim    *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
496218885Sdim  }
497218885Sdim}
498218885Sdim
499309124Sdimstatic void
500321369SdimgetIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
501321369Sdim                                unsigned Brand_id, unsigned Features,
502321369Sdim                                unsigned Features2, unsigned *Type,
503321369Sdim                                unsigned *Subtype) {
504309124Sdim  if (Brand_id != 0)
505309124Sdim    return;
506309124Sdim  switch (Family) {
507309124Sdim  case 3:
508327952Sdim    *Type = X86::INTEL_i386;
509309124Sdim    break;
510309124Sdim  case 4:
511327952Sdim    *Type = X86::INTEL_i486;
512309124Sdim    break;
513309124Sdim  case 5:
514327952Sdim    if (Features & (1 << X86::FEATURE_MMX)) {
515327952Sdim      *Type = X86::INTEL_PENTIUM_MMX;
516309124Sdim      break;
517309124Sdim    }
518327952Sdim    *Type = X86::INTEL_PENTIUM;
519309124Sdim    break;
520309124Sdim  case 6:
521309124Sdim    switch (Model) {
522309124Sdim    case 0x01: // Pentium Pro processor
523327952Sdim      *Type = X86::INTEL_PENTIUM_PRO;
524309124Sdim      break;
525309124Sdim    case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
526218885Sdim               // model 03
527309124Sdim    case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
528218885Sdim               // model 05, and Intel Celeron processor, model 05
529309124Sdim    case 0x06: // Celeron processor, model 06
530327952Sdim      *Type = X86::INTEL_PENTIUM_II;
531309124Sdim      break;
532309124Sdim    case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
533218885Sdim               // processor, model 07
534309124Sdim    case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
535218885Sdim               // model 08, and Celeron processor, model 08
536309124Sdim    case 0x0a: // Pentium III Xeon processor, model 0Ah
537309124Sdim    case 0x0b: // Pentium III processor, model 0Bh
538327952Sdim      *Type = X86::INTEL_PENTIUM_III;
539309124Sdim      break;
540309124Sdim    case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
541309124Sdim    case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
542218885Sdim               // 0Dh. All processors are manufactured using the 90 nm process.
543309124Sdim    case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
544288943Sdim               // Integrated Processor with Intel QuickAssist Technology
545327952Sdim      *Type = X86::INTEL_PENTIUM_M;
546309124Sdim      break;
547309124Sdim    case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
548218885Sdim               // 0Eh. All processors are manufactured using the 65 nm process.
549327952Sdim      *Type = X86::INTEL_CORE_DUO;
550309124Sdim      break;   // yonah
551309124Sdim    case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
552218885Sdim               // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
553218885Sdim               // mobile processor, Intel Core 2 Extreme processor, Intel
554218885Sdim               // Pentium Dual-Core processor, Intel Xeon processor, model
555218885Sdim               // 0Fh. All processors are manufactured using the 65 nm process.
556309124Sdim    case 0x16: // Intel Celeron processor model 16h. All processors are
557218885Sdim               // manufactured using the 65 nm process
558327952Sdim      *Type = X86::INTEL_CORE2; // "core2"
559327952Sdim      *Subtype = X86::INTEL_CORE2_65;
560309124Sdim      break;
561309124Sdim    case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
562218885Sdim               // 17h. All processors are manufactured using the 45 nm process.
563218885Sdim               //
564218885Sdim               // 45nm: Penryn , Wolfdale, Yorkfield (XE)
565309124Sdim    case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
566288943Sdim               // the 45 nm process.
567327952Sdim      *Type = X86::INTEL_CORE2; // "penryn"
568327952Sdim      *Subtype = X86::INTEL_CORE2_45;
569309124Sdim      break;
570309124Sdim    case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
571218885Sdim               // processors are manufactured using the 45 nm process.
572309124Sdim    case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
573218885Sdim               // As found in a Summer 2010 model iMac.
574309124Sdim    case 0x1f:
575309124Sdim    case 0x2e:             // Nehalem EX
576327952Sdim      *Type = X86::INTEL_COREI7; // "nehalem"
577327952Sdim      *Subtype = X86::INTEL_COREI7_NEHALEM;
578309124Sdim      break;
579309124Sdim    case 0x25: // Intel Core i7, laptop version.
580309124Sdim    case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
581226633Sdim               // processors are manufactured using the 32 nm process.
582309124Sdim    case 0x2f: // Westmere EX
583327952Sdim      *Type = X86::INTEL_COREI7; // "westmere"
584327952Sdim      *Subtype = X86::INTEL_COREI7_WESTMERE;
585309124Sdim      break;
586309124Sdim    case 0x2a: // Intel Core i7 processor. All processors are manufactured
587224145Sdim               // using the 32 nm process.
588309124Sdim    case 0x2d:
589327952Sdim      *Type = X86::INTEL_COREI7; //"sandybridge"
590327952Sdim      *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
591309124Sdim      break;
592309124Sdim    case 0x3a:
593309124Sdim    case 0x3e:             // Ivy Bridge EP
594327952Sdim      *Type = X86::INTEL_COREI7; // "ivybridge"
595327952Sdim      *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
596309124Sdim      break;
597218885Sdim
598309124Sdim    // Haswell:
599309124Sdim    case 0x3c:
600309124Sdim    case 0x3f:
601309124Sdim    case 0x45:
602309124Sdim    case 0x46:
603327952Sdim      *Type = X86::INTEL_COREI7; // "haswell"
604327952Sdim      *Subtype = X86::INTEL_COREI7_HASWELL;
605309124Sdim      break;
606239462Sdim
607309124Sdim    // Broadwell:
608309124Sdim    case 0x3d:
609309124Sdim    case 0x47:
610309124Sdim    case 0x4f:
611309124Sdim    case 0x56:
612327952Sdim      *Type = X86::INTEL_COREI7; // "broadwell"
613327952Sdim      *Subtype = X86::INTEL_COREI7_BROADWELL;
614309124Sdim      break;
615261991Sdim
616309124Sdim    // Skylake:
617314564Sdim    case 0x4e: // Skylake mobile
618314564Sdim    case 0x5e: // Skylake desktop
619314564Sdim    case 0x8e: // Kaby Lake mobile
620314564Sdim    case 0x9e: // Kaby Lake desktop
621327952Sdim      *Type = X86::INTEL_COREI7; // "skylake"
622327952Sdim      *Subtype = X86::INTEL_COREI7_SKYLAKE;
623309124Sdim      break;
624288943Sdim
625314564Sdim    // Skylake Xeon:
626314564Sdim    case 0x55:
627327952Sdim      *Type = X86::INTEL_COREI7;
628327952Sdim      *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512"
629314564Sdim      break;
630314564Sdim
631327952Sdim    // Cannonlake:
632327952Sdim    case 0x66:
633327952Sdim      *Type = X86::INTEL_COREI7;
634327952Sdim      *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake"
635327952Sdim      break;
636327952Sdim
637309124Sdim    case 0x1c: // Most 45 nm Intel Atom processors
638309124Sdim    case 0x26: // 45 nm Atom Lincroft
639309124Sdim    case 0x27: // 32 nm Atom Medfield
640309124Sdim    case 0x35: // 32 nm Atom Midview
641309124Sdim    case 0x36: // 32 nm Atom Midview
642327952Sdim      *Type = X86::INTEL_BONNELL;
643309124Sdim      break; // "bonnell"
644296417Sdim
645309124Sdim    // Atom Silvermont codes from the Intel software optimization guide.
646309124Sdim    case 0x37:
647309124Sdim    case 0x4a:
648309124Sdim    case 0x4d:
649309124Sdim    case 0x5a:
650309124Sdim    case 0x5d:
651309124Sdim    case 0x4c: // really airmont
652327952Sdim      *Type = X86::INTEL_SILVERMONT;
653309124Sdim      break; // "silvermont"
654321369Sdim    // Goldmont:
655327952Sdim    case 0x5c: // Apollo Lake
656327952Sdim    case 0x5f: // Denverton
657327952Sdim    case 0x7a: // Gemini Lake
658327952Sdim      *Type = X86::INTEL_GOLDMONT;
659321369Sdim      break; // "goldmont"
660309124Sdim    case 0x57:
661327952Sdim      *Type = X86::INTEL_KNL; // knl
662309124Sdim      break;
663327952Sdim    case 0x85:
664327952Sdim      *Type = X86::INTEL_KNM; // knm
665327952Sdim      break;
666261991Sdim
667309124Sdim    default: // Unknown family 6 CPU, try to guess.
668327952Sdim      if (Features & (1 << X86::FEATURE_AVX512VBMI)) {
669327952Sdim        *Type = X86::INTEL_COREI7;
670327952Sdim        *Subtype = X86::INTEL_COREI7_CANNONLAKE;
671309124Sdim        break;
672218885Sdim      }
673327952Sdim
674327952Sdim      if (Features & (1 << X86::FEATURE_AVX512VL)) {
675327952Sdim        *Type = X86::INTEL_COREI7;
676327952Sdim        *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
677309124Sdim        break;
678309124Sdim      }
679327952Sdim
680327952Sdim      if (Features & (1 << X86::FEATURE_AVX512ER)) {
681327952Sdim        *Type = X86::INTEL_KNL; // knl
682309124Sdim        break;
683309124Sdim      }
684327952Sdim
685327952Sdim      if (Features2 & (1 << (X86::FEATURE_CLFLUSHOPT - 32))) {
686327952Sdim        if (Features2 & (1 << (X86::FEATURE_SHA - 32))) {
687327952Sdim          *Type = X86::INTEL_GOLDMONT;
688327952Sdim        } else {
689327952Sdim          *Type = X86::INTEL_COREI7;
690327952Sdim          *Subtype = X86::INTEL_COREI7_SKYLAKE;
691327952Sdim        }
692309124Sdim        break;
693309124Sdim      }
694327952Sdim      if (Features2 & (1 << (X86::FEATURE_ADX - 32))) {
695327952Sdim        *Type = X86::INTEL_COREI7;
696327952Sdim        *Subtype = X86::INTEL_COREI7_BROADWELL;
697327952Sdim        break;
698327952Sdim      }
699327952Sdim      if (Features & (1 << X86::FEATURE_AVX2)) {
700327952Sdim        *Type = X86::INTEL_COREI7;
701327952Sdim        *Subtype = X86::INTEL_COREI7_HASWELL;
702327952Sdim        break;
703327952Sdim      }
704327952Sdim      if (Features & (1 << X86::FEATURE_AVX)) {
705327952Sdim        *Type = X86::INTEL_COREI7;
706327952Sdim        *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
707327952Sdim        break;
708327952Sdim      }
709327952Sdim      if (Features & (1 << X86::FEATURE_SSE4_2)) {
710327952Sdim        if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) {
711327952Sdim          *Type = X86::INTEL_SILVERMONT;
712309124Sdim        } else {
713327952Sdim          *Type = X86::INTEL_COREI7;
714327952Sdim          *Subtype = X86::INTEL_COREI7_NEHALEM;
715309124Sdim        }
716309124Sdim        break;
717309124Sdim      }
718327952Sdim      if (Features & (1 << X86::FEATURE_SSE4_1)) {
719327952Sdim        *Type = X86::INTEL_CORE2; // "penryn"
720327952Sdim        *Subtype = X86::INTEL_CORE2_45;
721309124Sdim        break;
722309124Sdim      }
723327952Sdim      if (Features & (1 << X86::FEATURE_SSSE3)) {
724327952Sdim        if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) {
725327952Sdim          *Type = X86::INTEL_BONNELL; // "bonnell"
726309124Sdim        } else {
727327952Sdim          *Type = X86::INTEL_CORE2; // "core2"
728327952Sdim          *Subtype = X86::INTEL_CORE2_65;
729309124Sdim        }
730309124Sdim        break;
731309124Sdim      }
732327952Sdim      if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) {
733327952Sdim        *Type = X86::INTEL_CORE2; // "core2"
734327952Sdim        *Subtype = X86::INTEL_CORE2_65;
735327952Sdim        break;
736309124Sdim      }
737327952Sdim      if (Features & (1 << X86::FEATURE_SSE3)) {
738327952Sdim        *Type = X86::INTEL_CORE_DUO;
739309124Sdim        break;
740309124Sdim      }
741327952Sdim      if (Features & (1 << X86::FEATURE_SSE2)) {
742327952Sdim        *Type = X86::INTEL_PENTIUM_M;
743309124Sdim        break;
744309124Sdim      }
745327952Sdim      if (Features & (1 << X86::FEATURE_SSE)) {
746327952Sdim        *Type = X86::INTEL_PENTIUM_III;
747309124Sdim        break;
748309124Sdim      }
749327952Sdim      if (Features & (1 << X86::FEATURE_MMX)) {
750327952Sdim        *Type = X86::INTEL_PENTIUM_II;
751327952Sdim        break;
752327952Sdim      }
753327952Sdim      *Type = X86::INTEL_PENTIUM_PRO;
754309124Sdim      break;
755309124Sdim    }
756309124Sdim    break;
757309124Sdim  case 15: {
758327952Sdim    if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) {
759327952Sdim      *Type = X86::INTEL_NOCONA;
760309124Sdim      break;
761327952Sdim    }
762327952Sdim    if (Features & (1 << X86::FEATURE_SSE3)) {
763327952Sdim      *Type = X86::INTEL_PRESCOTT;
764309124Sdim      break;
765218885Sdim    }
766327952Sdim    *Type = X86::INTEL_PENTIUM_IV;
767309124Sdim    break;
768309124Sdim  }
769309124Sdim  default:
770309124Sdim    break; /*"generic"*/
771309124Sdim  }
772309124Sdim}
773218885Sdim
774321369Sdimstatic void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
775321369Sdim                                          unsigned Features, unsigned *Type,
776309124Sdim                                          unsigned *Subtype) {
777309124Sdim  // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
778309124Sdim  // appears to be no way to generate the wide variety of AMD-specific targets
779309124Sdim  // from the information returned from CPUID.
780309124Sdim  switch (Family) {
781309124Sdim  case 4:
782327952Sdim    *Type = X86::AMD_i486;
783309124Sdim    break;
784309124Sdim  case 5:
785327952Sdim    *Type = X86::AMDPENTIUM;
786309124Sdim    switch (Model) {
787309124Sdim    case 6:
788309124Sdim    case 7:
789327952Sdim      *Subtype = X86::AMDPENTIUM_K6;
790309124Sdim      break; // "k6"
791309124Sdim    case 8:
792327952Sdim      *Subtype = X86::AMDPENTIUM_K62;
793309124Sdim      break; // "k6-2"
794309124Sdim    case 9:
795309124Sdim    case 13:
796327952Sdim      *Subtype = X86::AMDPENTIUM_K63;
797309124Sdim      break; // "k6-3"
798309124Sdim    case 10:
799327952Sdim      *Subtype = X86::AMDPENTIUM_GEODE;
800309124Sdim      break; // "geode"
801309124Sdim    }
802309124Sdim    break;
803309124Sdim  case 6:
804327952Sdim    if (Features & (1 << X86::FEATURE_SSE)) {
805327952Sdim      *Type = X86::AMD_ATHLON_XP;
806309124Sdim      break; // "athlon-xp"
807309124Sdim    }
808327952Sdim    *Type = X86::AMD_ATHLON;
809321369Sdim    break; // "athlon"
810309124Sdim  case 15:
811327952Sdim    if (Features & (1 << X86::FEATURE_SSE3)) {
812327952Sdim      *Type = X86::AMD_K8SSE3;
813309124Sdim      break; // "k8-sse3"
814309124Sdim    }
815327952Sdim    *Type = X86::AMD_K8;
816321369Sdim    break; // "k8"
817309124Sdim  case 16:
818327952Sdim    *Type = X86::AMDFAM10H; // "amdfam10"
819309124Sdim    switch (Model) {
820309124Sdim    case 2:
821327952Sdim      *Subtype = X86::AMDFAM10H_BARCELONA;
822309124Sdim      break;
823309124Sdim    case 4:
824327952Sdim      *Subtype = X86::AMDFAM10H_SHANGHAI;
825309124Sdim      break;
826309124Sdim    case 8:
827327952Sdim      *Subtype = X86::AMDFAM10H_ISTANBUL;
828309124Sdim      break;
829309124Sdim    }
830309124Sdim    break;
831309124Sdim  case 20:
832327952Sdim    *Type = X86::AMD_BTVER1;
833309124Sdim    break; // "btver1";
834309124Sdim  case 21:
835327952Sdim    *Type = X86::AMDFAM15H;
836321369Sdim    if (Model >= 0x60 && Model <= 0x7f) {
837327952Sdim      *Subtype = X86::AMDFAM15H_BDVER4;
838321369Sdim      break; // "bdver4"; 60h-7Fh: Excavator
839309124Sdim    }
840309124Sdim    if (Model >= 0x30 && Model <= 0x3f) {
841327952Sdim      *Subtype = X86::AMDFAM15H_BDVER3;
842309124Sdim      break; // "bdver3"; 30h-3Fh: Steamroller
843309124Sdim    }
844309124Sdim    if (Model >= 0x10 && Model <= 0x1f) {
845327952Sdim      *Subtype = X86::AMDFAM15H_BDVER2;
846309124Sdim      break; // "bdver2"; 10h-1Fh: Piledriver
847309124Sdim    }
848309124Sdim    if (Model <= 0x0f) {
849327952Sdim      *Subtype = X86::AMDFAM15H_BDVER1;
850309124Sdim      break; // "bdver1"; 00h-0Fh: Bulldozer
851309124Sdim    }
852309124Sdim    break;
853309124Sdim  case 22:
854327952Sdim    *Type = X86::AMD_BTVER2;
855309124Sdim    break; // "btver2"
856314564Sdim  case 23:
857327952Sdim    *Type = X86::AMDFAM17H;
858327952Sdim    *Subtype = X86::AMDFAM17H_ZNVER1;
859314564Sdim    break;
860309124Sdim  default:
861309124Sdim    break; // "generic"
862309124Sdim  }
863309124Sdim}
864309124Sdim
865321369Sdimstatic void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
866321369Sdim                                 unsigned *FeaturesOut,
867321369Sdim                                 unsigned *Features2Out) {
868309124Sdim  unsigned Features = 0;
869321369Sdim  unsigned Features2 = 0;
870321369Sdim  unsigned EAX, EBX;
871309124Sdim
872321369Sdim  if ((EDX >> 15) & 1)
873327952Sdim    Features |= 1 << X86::FEATURE_CMOV;
874321369Sdim  if ((EDX >> 23) & 1)
875327952Sdim    Features |= 1 << X86::FEATURE_MMX;
876321369Sdim  if ((EDX >> 25) & 1)
877327952Sdim    Features |= 1 << X86::FEATURE_SSE;
878321369Sdim  if ((EDX >> 26) & 1)
879327952Sdim    Features |= 1 << X86::FEATURE_SSE2;
880321369Sdim
881321369Sdim  if ((ECX >> 0) & 1)
882327952Sdim    Features |= 1 << X86::FEATURE_SSE3;
883321369Sdim  if ((ECX >> 1) & 1)
884327952Sdim    Features |= 1 << X86::FEATURE_PCLMUL;
885321369Sdim  if ((ECX >> 9) & 1)
886327952Sdim    Features |= 1 << X86::FEATURE_SSSE3;
887321369Sdim  if ((ECX >> 12) & 1)
888327952Sdim    Features |= 1 << X86::FEATURE_FMA;
889321369Sdim  if ((ECX >> 19) & 1)
890327952Sdim    Features |= 1 << X86::FEATURE_SSE4_1;
891321369Sdim  if ((ECX >> 20) & 1)
892327952Sdim    Features |= 1 << X86::FEATURE_SSE4_2;
893321369Sdim  if ((ECX >> 23) & 1)
894327952Sdim    Features |= 1 << X86::FEATURE_POPCNT;
895321369Sdim  if ((ECX >> 25) & 1)
896327952Sdim    Features |= 1 << X86::FEATURE_AES;
897321369Sdim
898321369Sdim  if ((ECX >> 22) & 1)
899327952Sdim    Features2 |= 1 << (X86::FEATURE_MOVBE - 32);
900321369Sdim
901309124Sdim  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
902309124Sdim  // indicates that the AVX registers will be saved and restored on context
903309124Sdim  // switch, then we have full AVX support.
904309124Sdim  const unsigned AVXBits = (1 << 27) | (1 << 28);
905309124Sdim  bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
906309124Sdim                ((EAX & 0x6) == 0x6);
907309124Sdim  bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
908321369Sdim
909321369Sdim  if (HasAVX)
910327952Sdim    Features |= 1 << X86::FEATURE_AVX;
911321369Sdim
912309124Sdim  bool HasLeaf7 =
913309124Sdim      MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
914309124Sdim
915321369Sdim  if (HasLeaf7 && ((EBX >> 3) & 1))
916327952Sdim    Features |= 1 << X86::FEATURE_BMI;
917321369Sdim  if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
918327952Sdim    Features |= 1 << X86::FEATURE_AVX2;
919321369Sdim  if (HasLeaf7 && ((EBX >> 9) & 1))
920327952Sdim    Features |= 1 << X86::FEATURE_BMI2;
921321369Sdim  if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
922327952Sdim    Features |= 1 << X86::FEATURE_AVX512F;
923321369Sdim  if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
924327952Sdim    Features |= 1 << X86::FEATURE_AVX512DQ;
925321369Sdim  if (HasLeaf7 && ((EBX >> 19) & 1))
926327952Sdim    Features2 |= 1 << (X86::FEATURE_ADX - 32);
927321369Sdim  if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
928327952Sdim    Features |= 1 << X86::FEATURE_AVX512IFMA;
929327952Sdim  if (HasLeaf7 && ((EBX >> 23) & 1))
930327952Sdim    Features2 |= 1 << (X86::FEATURE_CLFLUSHOPT - 32);
931321369Sdim  if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
932327952Sdim    Features |= 1 << X86::FEATURE_AVX512PF;
933321369Sdim  if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
934327952Sdim    Features |= 1 << X86::FEATURE_AVX512ER;
935321369Sdim  if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
936327952Sdim    Features |= 1 << X86::FEATURE_AVX512CD;
937327952Sdim  if (HasLeaf7 && ((EBX >> 29) & 1))
938327952Sdim    Features2 |= 1 << (X86::FEATURE_SHA - 32);
939321369Sdim  if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
940327952Sdim    Features |= 1 << X86::FEATURE_AVX512BW;
941321369Sdim  if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
942327952Sdim    Features |= 1 << X86::FEATURE_AVX512VL;
943321369Sdim
944321369Sdim  if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
945327952Sdim    Features |= 1 << X86::FEATURE_AVX512VBMI;
946321369Sdim  if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
947327952Sdim    Features |= 1 << X86::FEATURE_AVX512VPOPCNTDQ;
948321369Sdim
949321369Sdim  if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
950327952Sdim    Features |= 1 << X86::FEATURE_AVX5124VNNIW;
951321369Sdim  if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
952327952Sdim    Features |= 1 << X86::FEATURE_AVX5124FMAPS;
953321369Sdim
954321369Sdim  unsigned MaxExtLevel;
955321369Sdim  getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
956321369Sdim
957321369Sdim  bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
958321369Sdim                     !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
959321369Sdim  if (HasExtLeaf1 && ((ECX >> 6) & 1))
960327952Sdim    Features |= 1 << X86::FEATURE_SSE4_A;
961321369Sdim  if (HasExtLeaf1 && ((ECX >> 11) & 1))
962327952Sdim    Features |= 1 << X86::FEATURE_XOP;
963321369Sdim  if (HasExtLeaf1 && ((ECX >> 16) & 1))
964327952Sdim    Features |= 1 << X86::FEATURE_FMA4;
965321369Sdim
966321369Sdim  if (HasExtLeaf1 && ((EDX >> 29) & 1))
967327952Sdim    Features2 |= 1 << (X86::FEATURE_EM64T - 32);
968321369Sdim
969321369Sdim  *FeaturesOut  = Features;
970321369Sdim  *Features2Out = Features2;
971309124Sdim}
972309124Sdim
973309124SdimStringRef sys::getHostCPUName() {
974309124Sdim  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
975309124Sdim  unsigned MaxLeaf, Vendor;
976309124Sdim
977314564Sdim#if defined(__GNUC__) || defined(__clang__)
978314564Sdim  //FIXME: include cpuid.h from clang or copy __get_cpuid_max here
979314564Sdim  // and simplify it to not invoke __cpuid (like cpu_model.c in
980314564Sdim  // compiler-rt/lib/builtins/cpu_model.c?
981314564Sdim  // Opting for the second option.
982314564Sdim  if(!isCpuIdSupported())
983314564Sdim    return "generic";
984314564Sdim#endif
985321369Sdim  if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1)
986309124Sdim    return "generic";
987321369Sdim  getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
988309124Sdim
989309124Sdim  unsigned Brand_id = EBX & 0xff;
990309124Sdim  unsigned Family = 0, Model = 0;
991321369Sdim  unsigned Features = 0, Features2 = 0;
992309124Sdim  detectX86FamilyModel(EAX, &Family, &Model);
993321369Sdim  getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2);
994309124Sdim
995327952Sdim  unsigned Type = 0;
996327952Sdim  unsigned Subtype = 0;
997309124Sdim
998309124Sdim  if (Vendor == SIG_INTEL) {
999321369Sdim    getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features,
1000321369Sdim                                    Features2, &Type, &Subtype);
1001309124Sdim  } else if (Vendor == SIG_AMD) {
1002309124Sdim    getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
1003218885Sdim  }
1004327952Sdim
1005327952Sdim  // Check subtypes first since those are more specific.
1006327952Sdim#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
1007327952Sdim  if (Subtype == X86::ENUM) \
1008327952Sdim    return ARCHNAME;
1009327952Sdim#include "llvm/Support/X86TargetParser.def"
1010327952Sdim
1011327952Sdim  // Now check types.
1012327952Sdim#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
1013327952Sdim  if (Type == X86::ENUM) \
1014327952Sdim    return ARCHNAME;
1015327952Sdim#include "llvm/Support/X86TargetParser.def"
1016327952Sdim
1017218885Sdim  return "generic";
1018218885Sdim}
1019309124Sdim
1020239462Sdim#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
1021276479SdimStringRef sys::getHostCPUName() {
1022239462Sdim  host_basic_info_data_t hostInfo;
1023239462Sdim  mach_msg_type_number_t infoCount;
1024239462Sdim
1025239462Sdim  infoCount = HOST_BASIC_INFO_COUNT;
1026309124Sdim  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
1027239462Sdim            &infoCount);
1028239462Sdim
1029309124Sdim  if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
1030309124Sdim    return "generic";
1031309124Sdim
1032309124Sdim  switch (hostInfo.cpu_subtype) {
1033309124Sdim  case CPU_SUBTYPE_POWERPC_601:
1034309124Sdim    return "601";
1035309124Sdim  case CPU_SUBTYPE_POWERPC_602:
1036309124Sdim    return "602";
1037309124Sdim  case CPU_SUBTYPE_POWERPC_603:
1038309124Sdim    return "603";
1039309124Sdim  case CPU_SUBTYPE_POWERPC_603e:
1040309124Sdim    return "603e";
1041309124Sdim  case CPU_SUBTYPE_POWERPC_603ev:
1042309124Sdim    return "603ev";
1043309124Sdim  case CPU_SUBTYPE_POWERPC_604:
1044309124Sdim    return "604";
1045309124Sdim  case CPU_SUBTYPE_POWERPC_604e:
1046309124Sdim    return "604e";
1047309124Sdim  case CPU_SUBTYPE_POWERPC_620:
1048309124Sdim    return "620";
1049309124Sdim  case CPU_SUBTYPE_POWERPC_750:
1050309124Sdim    return "750";
1051309124Sdim  case CPU_SUBTYPE_POWERPC_7400:
1052309124Sdim    return "7400";
1053309124Sdim  case CPU_SUBTYPE_POWERPC_7450:
1054309124Sdim    return "7450";
1055309124Sdim  case CPU_SUBTYPE_POWERPC_970:
1056309124Sdim    return "970";
1057309124Sdim  default:;
1058239462Sdim  }
1059309124Sdim
1060239462Sdim  return "generic";
1061239462Sdim}
1062239462Sdim#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
1063276479SdimStringRef sys::getHostCPUName() {
1064321369Sdim  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1065321369Sdim  const StringRef& Content = P ? P->getBuffer() : "";
1066321369Sdim  return detail::getHostCPUNameForPowerPC(Content);
1067239462Sdim}
1068321369Sdim#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1069276479SdimStringRef sys::getHostCPUName() {
1070321369Sdim  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1071321369Sdim  const StringRef& Content = P ? P->getBuffer() : "";
1072321369Sdim  return detail::getHostCPUNameForARM(Content);
1073239462Sdim}
1074261991Sdim#elif defined(__linux__) && defined(__s390x__)
1075276479SdimStringRef sys::getHostCPUName() {
1076321369Sdim  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1077321369Sdim  const StringRef& Content = P ? P->getBuffer() : "";
1078321369Sdim  return detail::getHostCPUNameForS390x(Content);
1079261991Sdim}
1080218885Sdim#else
1081309124SdimStringRef sys::getHostCPUName() { return "generic"; }
1082218885Sdim#endif
1083218885Sdim
1084314564Sdim#if defined(__linux__) && defined(__x86_64__)
1085314564Sdim// On Linux, the number of physical cores can be computed from /proc/cpuinfo,
1086314564Sdim// using the number of unique physical/core id pairs. The following
1087314564Sdim// implementation reads the /proc/cpuinfo format on an x86_64 system.
1088314564Sdimstatic int computeHostNumPhysicalCores() {
1089314564Sdim  // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be
1090314564Sdim  // mmapped because it appears to have 0 size.
1091314564Sdim  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
1092314564Sdim      llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
1093314564Sdim  if (std::error_code EC = Text.getError()) {
1094314564Sdim    llvm::errs() << "Can't read "
1095314564Sdim                 << "/proc/cpuinfo: " << EC.message() << "\n";
1096321369Sdim    return -1;
1097314564Sdim  }
1098314564Sdim  SmallVector<StringRef, 8> strs;
1099314564Sdim  (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
1100314564Sdim                             /*KeepEmpty=*/false);
1101314564Sdim  int CurPhysicalId = -1;
1102314564Sdim  int CurCoreId = -1;
1103314564Sdim  SmallSet<std::pair<int, int>, 32> UniqueItems;
1104314564Sdim  for (auto &Line : strs) {
1105314564Sdim    Line = Line.trim();
1106314564Sdim    if (!Line.startswith("physical id") && !Line.startswith("core id"))
1107314564Sdim      continue;
1108314564Sdim    std::pair<StringRef, StringRef> Data = Line.split(':');
1109314564Sdim    auto Name = Data.first.trim();
1110314564Sdim    auto Val = Data.second.trim();
1111314564Sdim    if (Name == "physical id") {
1112314564Sdim      assert(CurPhysicalId == -1 &&
1113314564Sdim             "Expected a core id before seeing another physical id");
1114314564Sdim      Val.getAsInteger(10, CurPhysicalId);
1115314564Sdim    }
1116314564Sdim    if (Name == "core id") {
1117314564Sdim      assert(CurCoreId == -1 &&
1118314564Sdim             "Expected a physical id before seeing another core id");
1119314564Sdim      Val.getAsInteger(10, CurCoreId);
1120314564Sdim    }
1121314564Sdim    if (CurPhysicalId != -1 && CurCoreId != -1) {
1122314564Sdim      UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
1123314564Sdim      CurPhysicalId = -1;
1124314564Sdim      CurCoreId = -1;
1125314564Sdim    }
1126314564Sdim  }
1127314564Sdim  return UniqueItems.size();
1128314564Sdim}
1129314564Sdim#elif defined(__APPLE__) && defined(__x86_64__)
1130314564Sdim#include <sys/param.h>
1131314564Sdim#include <sys/sysctl.h>
1132314564Sdim
1133314564Sdim// Gets the number of *physical cores* on the machine.
1134314564Sdimstatic int computeHostNumPhysicalCores() {
1135314564Sdim  uint32_t count;
1136314564Sdim  size_t len = sizeof(count);
1137314564Sdim  sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
1138314564Sdim  if (count < 1) {
1139314564Sdim    int nm[2];
1140314564Sdim    nm[0] = CTL_HW;
1141314564Sdim    nm[1] = HW_AVAILCPU;
1142314564Sdim    sysctl(nm, 2, &count, &len, NULL, 0);
1143314564Sdim    if (count < 1)
1144314564Sdim      return -1;
1145314564Sdim  }
1146314564Sdim  return count;
1147314564Sdim}
1148314564Sdim#else
1149314564Sdim// On other systems, return -1 to indicate unknown.
1150314564Sdimstatic int computeHostNumPhysicalCores() { return -1; }
1151314564Sdim#endif
1152314564Sdim
1153314564Sdimint sys::getHostNumPhysicalCores() {
1154314564Sdim  static int NumCores = computeHostNumPhysicalCores();
1155314564Sdim  return NumCores;
1156314564Sdim}
1157314564Sdim
1158314564Sdim#if defined(__i386__) || defined(_M_IX86) || \
1159314564Sdim    defined(__x86_64__) || defined(_M_X64)
1160249423Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1161288943Sdim  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1162288943Sdim  unsigned MaxLevel;
1163288943Sdim  union {
1164288943Sdim    unsigned u[3];
1165309124Sdim    char c[12];
1166288943Sdim  } text;
1167288943Sdim
1168309124Sdim  if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
1169288943Sdim      MaxLevel < 1)
1170288943Sdim    return false;
1171288943Sdim
1172309124Sdim  getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1173288943Sdim
1174327952Sdim  Features["cmov"]   = (EDX >> 15) & 1;
1175327952Sdim  Features["mmx"]    = (EDX >> 23) & 1;
1176327952Sdim  Features["sse"]    = (EDX >> 25) & 1;
1177327952Sdim  Features["sse2"]   = (EDX >> 26) & 1;
1178327952Sdim
1179327952Sdim  Features["sse3"]   = (ECX >>  0) & 1;
1180327952Sdim  Features["pclmul"] = (ECX >>  1) & 1;
1181327952Sdim  Features["ssse3"]  = (ECX >>  9) & 1;
1182327952Sdim  Features["cx16"]   = (ECX >> 13) & 1;
1183288943Sdim  Features["sse4.1"] = (ECX >> 19) & 1;
1184288943Sdim  Features["sse4.2"] = (ECX >> 20) & 1;
1185327952Sdim  Features["movbe"]  = (ECX >> 22) & 1;
1186288943Sdim  Features["popcnt"] = (ECX >> 23) & 1;
1187327952Sdim  Features["aes"]    = (ECX >> 25) & 1;
1188327952Sdim  Features["rdrnd"]  = (ECX >> 30) & 1;
1189288943Sdim
1190288943Sdim  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1191288943Sdim  // indicates that the AVX registers will be saved and restored on context
1192288943Sdim  // switch, then we have full AVX support.
1193296417Sdim  bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
1194309124Sdim                    !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
1195327952Sdim  // AVX512 requires additional context to be saved by the OS.
1196327952Sdim  bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1197288943Sdim
1198327952Sdim  Features["avx"]   = HasAVXSave;
1199327952Sdim  Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;
1200296417Sdim  // Only enable XSAVE if OS has enabled support for saving YMM state.
1201327952Sdim  Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1202327952Sdim  Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;
1203296417Sdim
1204288943Sdim  unsigned MaxExtLevel;
1205309124Sdim  getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1206288943Sdim
1207288943Sdim  bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1208309124Sdim                     !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1209327952Sdim  Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);
1210327952Sdim  Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);
1211327952Sdim  Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);
1212327952Sdim  Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1213327952Sdim  Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);
1214327952Sdim  Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1215327952Sdim  Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);
1216309124Sdim  Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1217288943Sdim
1218321369Sdim  bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
1219327952Sdim                     !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
1220321369Sdim  Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1);
1221321369Sdim
1222309124Sdim  bool HasLeaf7 =
1223309124Sdim      MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1224288943Sdim
1225327952Sdim  Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);
1226327952Sdim  Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);
1227327952Sdim  Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);
1228288943Sdim  // AVX2 is only supported if we have the OS save support from AVX.
1229327952Sdim  Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;
1230327952Sdim  Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);
1231327952Sdim  Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);
1232288943Sdim  // AVX512 is only supported if the OS supports the context save for it.
1233327952Sdim  Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1234327952Sdim  Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1235327952Sdim  Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);
1236327952Sdim  Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);
1237309124Sdim  Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
1238327952Sdim  Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1239327952Sdim  Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);
1240327952Sdim  Features["avx512pf"]   = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
1241327952Sdim  Features["avx512er"]   = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
1242327952Sdim  Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1243327952Sdim  Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);
1244327952Sdim  Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1245327952Sdim  Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
1246288943Sdim
1247327952Sdim  Features["prefetchwt1"]     = HasLeaf7 && ((ECX >>  0) & 1);
1248327952Sdim  Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;
1249327952Sdim  Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);
1250327952Sdim  Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;
1251327952Sdim  Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);
1252327952Sdim  Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);
1253327952Sdim  Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;
1254327952Sdim  Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1255327952Sdim  Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1256327952Sdim  Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
1257327952Sdim  Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
1258327952Sdim  Features["ibt"]             = HasLeaf7 && ((EDX >> 20) & 1);
1259309124Sdim
1260296417Sdim  bool HasLeafD = MaxLevel >= 0xd &&
1261309124Sdim                  !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1262296417Sdim
1263296417Sdim  // Only enable XSAVE if OS has enabled support for saving YMM state.
1264327952Sdim  Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1265327952Sdim  Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1266327952Sdim  Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
1267296417Sdim
1268288943Sdim  return true;
1269288943Sdim}
1270288943Sdim#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1271288943Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1272321369Sdim  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1273321369Sdim  if (!P)
1274280031Sdim    return false;
1275249423Sdim
1276249423Sdim  SmallVector<StringRef, 32> Lines;
1277321369Sdim  P->getBuffer().split(Lines, "\n");
1278249423Sdim
1279261991Sdim  SmallVector<StringRef, 32> CPUFeatures;
1280261991Sdim
1281261991Sdim  // Look for the CPU features.
1282249423Sdim  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
1283261991Sdim    if (Lines[I].startswith("Features")) {
1284296417Sdim      Lines[I].split(CPUFeatures, ' ');
1285261991Sdim      break;
1286261991Sdim    }
1287249423Sdim
1288276479Sdim#if defined(__aarch64__)
1289276479Sdim  // Keep track of which crypto features we have seen
1290309124Sdim  enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
1291276479Sdim  uint32_t crypto = 0;
1292276479Sdim#endif
1293276479Sdim
1294261991Sdim  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
1295261991Sdim    StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
1296276479Sdim#if defined(__aarch64__)
1297309124Sdim                                   .Case("asimd", "neon")
1298309124Sdim                                   .Case("fp", "fp-armv8")
1299309124Sdim                                   .Case("crc32", "crc")
1300276479Sdim#else
1301309124Sdim                                   .Case("half", "fp16")
1302309124Sdim                                   .Case("neon", "neon")
1303309124Sdim                                   .Case("vfpv3", "vfp3")
1304309124Sdim                                   .Case("vfpv3d16", "d16")
1305309124Sdim                                   .Case("vfpv4", "vfp4")
1306309124Sdim                                   .Case("idiva", "hwdiv-arm")
1307309124Sdim                                   .Case("idivt", "hwdiv")
1308276479Sdim#endif
1309309124Sdim                                   .Default("");
1310249423Sdim
1311276479Sdim#if defined(__aarch64__)
1312276479Sdim    // We need to check crypto separately since we need all of the crypto
1313276479Sdim    // extensions to enable the subtarget feature
1314276479Sdim    if (CPUFeatures[I] == "aes")
1315276479Sdim      crypto |= CAP_AES;
1316276479Sdim    else if (CPUFeatures[I] == "pmull")
1317276479Sdim      crypto |= CAP_PMULL;
1318276479Sdim    else if (CPUFeatures[I] == "sha1")
1319276479Sdim      crypto |= CAP_SHA1;
1320276479Sdim    else if (CPUFeatures[I] == "sha2")
1321276479Sdim      crypto |= CAP_SHA2;
1322276479Sdim#endif
1323276479Sdim
1324261991Sdim    if (LLVMFeatureStr != "")
1325280031Sdim      Features[LLVMFeatureStr] = true;
1326249423Sdim  }
1327249423Sdim
1328276479Sdim#if defined(__aarch64__)
1329276479Sdim  // If we have all crypto bits we can add the feature
1330276479Sdim  if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
1331280031Sdim    Features["crypto"] = true;
1332276479Sdim#endif
1333276479Sdim
1334261991Sdim  return true;
1335249423Sdim}
1336249423Sdim#else
1337309124Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
1338249423Sdim#endif
1339249423Sdim
1340249423Sdimstd::string sys::getProcessTriple() {
1341321369Sdim  std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
1342321369Sdim  Triple PT(Triple::normalize(TargetTripleString));
1343249423Sdim
1344249423Sdim  if (sizeof(void *) == 8 && PT.isArch32Bit())
1345249423Sdim    PT = PT.get64BitArchVariant();
1346249423Sdim  if (sizeof(void *) == 4 && PT.isArch64Bit())
1347249423Sdim    PT = PT.get32BitArchVariant();
1348249423Sdim
1349249423Sdim  return PT.str();
1350249423Sdim}
1351