blob: 3ce636ffcda46ccb3bf6e95522afb79faaf42548 [file] [log] [blame]
Simon Pilgrima271c542017-05-03 15:42:29 +00001//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the operating system Host concept.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Support/Host.h"
Craig Topperc77d00e2017-11-10 17:10:57 +000015#include "llvm/Support/TargetParser.h"
Simon Pilgrima271c542017-05-03 15:42:29 +000016#include "llvm/ADT/SmallSet.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/Config/config.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/MemoryBuffer.h"
25#include "llvm/Support/raw_ostream.h"
26#include <assert.h>
27#include <string.h>
28
29// Include the platform-specific parts of this class.
30#ifdef LLVM_ON_UNIX
31#include "Unix/Host.inc"
32#endif
33#ifdef LLVM_ON_WIN32
34#include "Windows/Host.inc"
35#endif
36#ifdef _MSC_VER
37#include <intrin.h>
38#endif
39#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
40#include <mach/host_info.h>
41#include <mach/mach.h>
42#include <mach/mach_host.h>
43#include <mach/machine.h>
44#endif
45
46#define DEBUG_TYPE "host-detection"
47
48//===----------------------------------------------------------------------===//
49//
50// Implementations of the CPU detection routines
51//
52//===----------------------------------------------------------------------===//
53
54using namespace llvm;
55
56static std::unique_ptr<llvm::MemoryBuffer>
57 LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
58 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
59 llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
60 if (std::error_code EC = Text.getError()) {
61 llvm::errs() << "Can't read "
62 << "/proc/cpuinfo: " << EC.message() << "\n";
63 return nullptr;
64 }
65 return std::move(*Text);
66}
67
68StringRef sys::detail::getHostCPUNameForPowerPC(
69 const StringRef &ProcCpuinfoContent) {
70 // Access to the Processor Version Register (PVR) on PowerPC is privileged,
71 // and so we must use an operating-system interface to determine the current
72 // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
73 const char *generic = "generic";
74
75 // The cpu line is second (after the 'processor: 0' line), so if this
76 // buffer is too small then something has changed (or is wrong).
77 StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
78 StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
79
80 StringRef::const_iterator CIP = CPUInfoStart;
81
82 StringRef::const_iterator CPUStart = 0;
83 size_t CPULen = 0;
84
85 // We need to find the first line which starts with cpu, spaces, and a colon.
86 // After the colon, there may be some additional spaces and then the cpu type.
87 while (CIP < CPUInfoEnd && CPUStart == 0) {
88 if (CIP < CPUInfoEnd && *CIP == '\n')
89 ++CIP;
90
91 if (CIP < CPUInfoEnd && *CIP == 'c') {
92 ++CIP;
93 if (CIP < CPUInfoEnd && *CIP == 'p') {
94 ++CIP;
95 if (CIP < CPUInfoEnd && *CIP == 'u') {
96 ++CIP;
97 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
98 ++CIP;
99
100 if (CIP < CPUInfoEnd && *CIP == ':') {
101 ++CIP;
102 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
103 ++CIP;
104
105 if (CIP < CPUInfoEnd) {
106 CPUStart = CIP;
107 while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
108 *CIP != ',' && *CIP != '\n'))
109 ++CIP;
110 CPULen = CIP - CPUStart;
111 }
112 }
113 }
114 }
115 }
116
117 if (CPUStart == 0)
118 while (CIP < CPUInfoEnd && *CIP != '\n')
119 ++CIP;
120 }
121
122 if (CPUStart == 0)
123 return generic;
124
125 return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
126 .Case("604e", "604e")
127 .Case("604", "604")
128 .Case("7400", "7400")
129 .Case("7410", "7400")
130 .Case("7447", "7400")
131 .Case("7455", "7450")
132 .Case("G4", "g4")
133 .Case("POWER4", "970")
134 .Case("PPC970FX", "970")
135 .Case("PPC970MP", "970")
136 .Case("G5", "g5")
137 .Case("POWER5", "g5")
138 .Case("A2", "a2")
139 .Case("POWER6", "pwr6")
140 .Case("POWER7", "pwr7")
141 .Case("POWER8", "pwr8")
142 .Case("POWER8E", "pwr8")
143 .Case("POWER8NVL", "pwr8")
144 .Case("POWER9", "pwr9")
145 .Default(generic);
146}
147
148StringRef sys::detail::getHostCPUNameForARM(
149 const StringRef &ProcCpuinfoContent) {
150 // The cpuid register on arm is not accessible from user space. On Linux,
151 // it is exposed through the /proc/cpuinfo file.
152
153 // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
154 // in all cases.
155 SmallVector<StringRef, 32> Lines;
156 ProcCpuinfoContent.split(Lines, "\n");
157
158 // Look for the CPU implementer line.
159 StringRef Implementer;
160 StringRef Hardware;
161 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
162 if (Lines[I].startswith("CPU implementer"))
163 Implementer = Lines[I].substr(15).ltrim("\t :");
164 if (Lines[I].startswith("Hardware"))
165 Hardware = Lines[I].substr(8).ltrim("\t :");
166 }
167
168 if (Implementer == "0x41") { // ARM Ltd.
169 // MSM8992/8994 may give cpu part for the core that the kernel is running on,
170 // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
171 if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996"))
172 return "cortex-a53";
173
174
175 // Look for the CPU part line.
176 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
177 if (Lines[I].startswith("CPU part"))
178 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
179 // values correspond to the "Part number" in the CP15/c0 register. The
180 // contents are specified in the various processor manuals.
181 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
182 .Case("0x926", "arm926ej-s")
183 .Case("0xb02", "mpcore")
184 .Case("0xb36", "arm1136j-s")
185 .Case("0xb56", "arm1156t2-s")
186 .Case("0xb76", "arm1176jz-s")
187 .Case("0xc08", "cortex-a8")
188 .Case("0xc09", "cortex-a9")
189 .Case("0xc0f", "cortex-a15")
190 .Case("0xc20", "cortex-m0")
191 .Case("0xc23", "cortex-m3")
192 .Case("0xc24", "cortex-m4")
193 .Case("0xd04", "cortex-a35")
194 .Case("0xd03", "cortex-a53")
195 .Case("0xd07", "cortex-a57")
196 .Case("0xd08", "cortex-a72")
197 .Case("0xd09", "cortex-a73")
198 .Default("generic");
199 }
200
201 if (Implementer == "0x51") // Qualcomm Technologies, Inc.
202 // Look for the CPU part line.
203 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
204 if (Lines[I].startswith("CPU part"))
205 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
206 // values correspond to the "Part number" in the CP15/c0 register. The
207 // contents are specified in the various processor manuals.
208 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
209 .Case("0x06f", "krait") // APQ8064
210 .Case("0x201", "kryo")
211 .Case("0x205", "kryo")
Eli Friedmanbde9fc72017-09-13 21:48:00 +0000212 .Case("0x211", "kryo")
213 .Case("0x800", "cortex-a73")
214 .Case("0x801", "cortex-a73")
Balaram Makama1e7ecc72017-09-22 17:46:36 +0000215 .Case("0xc00", "falkor")
Chad Rosier71070852017-09-25 14:05:00 +0000216 .Case("0xc01", "saphira")
Simon Pilgrima271c542017-05-03 15:42:29 +0000217 .Default("generic");
218
219 return "generic";
220}
221
222StringRef sys::detail::getHostCPUNameForS390x(
223 const StringRef &ProcCpuinfoContent) {
224 // STIDP is a privileged operation, so use /proc/cpuinfo instead.
225
226 // The "processor 0:" line comes after a fair amount of other information,
227 // including a cache breakdown, but this should be plenty.
228 SmallVector<StringRef, 32> Lines;
229 ProcCpuinfoContent.split(Lines, "\n");
230
231 // Look for the CPU features.
232 SmallVector<StringRef, 32> CPUFeatures;
233 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
234 if (Lines[I].startswith("features")) {
235 size_t Pos = Lines[I].find(":");
236 if (Pos != StringRef::npos) {
237 Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
238 break;
239 }
240 }
241
242 // We need to check for the presence of vector support independently of
243 // the machine type, since we may only use the vector register set when
244 // supported by the kernel (and hypervisor).
245 bool HaveVectorSupport = false;
246 for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
247 if (CPUFeatures[I] == "vx")
248 HaveVectorSupport = true;
249 }
250
251 // Now check the processor machine type.
252 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
253 if (Lines[I].startswith("processor ")) {
254 size_t Pos = Lines[I].find("machine = ");
255 if (Pos != StringRef::npos) {
256 Pos += sizeof("machine = ") - 1;
257 unsigned int Id;
258 if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
Ulrich Weigand2b3482f2017-07-17 17:41:11 +0000259 if (Id >= 3906 && HaveVectorSupport)
260 return "z14";
Simon Pilgrima271c542017-05-03 15:42:29 +0000261 if (Id >= 2964 && HaveVectorSupport)
262 return "z13";
263 if (Id >= 2827)
264 return "zEC12";
265 if (Id >= 2817)
266 return "z196";
267 }
268 }
269 break;
270 }
271 }
272
273 return "generic";
274}
275
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000276StringRef sys::detail::getHostCPUNameForBPF() {
277#if !defined(__linux__) || !defined(__x86_64__)
278 return "generic";
279#else
280 uint8_t insns[40] __attribute__ ((aligned (8))) =
281 /* BPF_MOV64_IMM(BPF_REG_0, 0) */
282 { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
283 /* BPF_MOV64_IMM(BPF_REG_2, 1) */
284 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
285 /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
286 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
287 /* BPF_MOV64_IMM(BPF_REG_0, 1) */
288 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
289 /* BPF_EXIT_INSN() */
290 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
291
292 struct bpf_prog_load_attr {
293 uint32_t prog_type;
294 uint32_t insn_cnt;
295 uint64_t insns;
296 uint64_t license;
297 uint32_t log_level;
298 uint32_t log_size;
299 uint64_t log_buf;
300 uint32_t kern_version;
301 uint32_t prog_flags;
302 } attr = {};
303 attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
304 attr.insn_cnt = 5;
305 attr.insns = (uint64_t)insns;
306 attr.license = (uint64_t)"DUMMY";
307
308 int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
Yonghong Songc6d25712017-08-23 16:24:31 +0000309 if (fd >= 0) {
310 close(fd);
311 return "v2";
312 }
313 return "v1";
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000314#endif
315}
316
Simon Pilgrima271c542017-05-03 15:42:29 +0000317#if defined(__i386__) || defined(_M_IX86) || \
318 defined(__x86_64__) || defined(_M_X64)
319
320enum VendorSignatures {
321 SIG_INTEL = 0x756e6547 /* Genu */,
322 SIG_AMD = 0x68747541 /* Auth */
323};
324
Simon Pilgrima271c542017-05-03 15:42:29 +0000325// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
326// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
327// support. Consequently, for i386, the presence of CPUID is checked first
328// via the corresponding eflags bit.
329// Removal of cpuid.h header motivated by PR30384
330// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
331// or test-suite, but are used in external projects e.g. libstdcxx
332static bool isCpuIdSupported() {
333#if defined(__GNUC__) || defined(__clang__)
334#if defined(__i386__)
335 int __cpuid_supported;
336 __asm__(" pushfl\n"
337 " popl %%eax\n"
338 " movl %%eax,%%ecx\n"
339 " xorl $0x00200000,%%eax\n"
340 " pushl %%eax\n"
341 " popfl\n"
342 " pushfl\n"
343 " popl %%eax\n"
344 " movl $0,%0\n"
345 " cmpl %%eax,%%ecx\n"
346 " je 1f\n"
347 " movl $1,%0\n"
348 "1:"
349 : "=r"(__cpuid_supported)
350 :
351 : "eax", "ecx");
352 if (!__cpuid_supported)
353 return false;
354#endif
355 return true;
356#endif
357 return true;
358}
359
360/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
361/// the specified arguments. If we can't run cpuid on the host, return true.
362static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
363 unsigned *rECX, unsigned *rEDX) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000364#if defined(__GNUC__) || defined(__clang__)
365#if defined(__x86_64__)
366 // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
367 // FIXME: should we save this for Clang?
368 __asm__("movq\t%%rbx, %%rsi\n\t"
369 "cpuid\n\t"
370 "xchgq\t%%rbx, %%rsi\n\t"
371 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
372 : "a"(value));
Craig Topper1efd10a2017-07-10 06:04:11 +0000373 return false;
Simon Pilgrima271c542017-05-03 15:42:29 +0000374#elif defined(__i386__)
375 __asm__("movl\t%%ebx, %%esi\n\t"
376 "cpuid\n\t"
377 "xchgl\t%%ebx, %%esi\n\t"
378 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
379 : "a"(value));
Craig Topper1efd10a2017-07-10 06:04:11 +0000380 return false;
Simon Pilgrima271c542017-05-03 15:42:29 +0000381#else
Craig Topper1efd10a2017-07-10 06:04:11 +0000382 return true;
Simon Pilgrima271c542017-05-03 15:42:29 +0000383#endif
384#elif defined(_MSC_VER)
385 // The MSVC intrinsic is portable across x86 and x64.
386 int registers[4];
387 __cpuid(registers, value);
388 *rEAX = registers[0];
389 *rEBX = registers[1];
390 *rECX = registers[2];
391 *rEDX = registers[3];
Simon Pilgrima271c542017-05-03 15:42:29 +0000392 return false;
393#else
394 return true;
395#endif
396}
397
398/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
399/// the 4 values in the specified arguments. If we can't run cpuid on the host,
400/// return true.
401static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
402 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
403 unsigned *rEDX) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000404#if defined(__GNUC__) || defined(__clang__)
Craig Topper828cf302017-07-17 05:16:16 +0000405#if defined(__x86_64__)
Craig Topperada983a2017-07-10 06:09:22 +0000406 // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
Simon Pilgrima271c542017-05-03 15:42:29 +0000407 // FIXME: should we save this for Clang?
408 __asm__("movq\t%%rbx, %%rsi\n\t"
409 "cpuid\n\t"
410 "xchgq\t%%rbx, %%rsi\n\t"
411 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
412 : "a"(value), "c"(subleaf));
Craig Topper1efd10a2017-07-10 06:04:11 +0000413 return false;
Craig Topper828cf302017-07-17 05:16:16 +0000414#elif defined(__i386__)
415 __asm__("movl\t%%ebx, %%esi\n\t"
416 "cpuid\n\t"
417 "xchgl\t%%ebx, %%esi\n\t"
418 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
419 : "a"(value), "c"(subleaf));
420 return false;
421#else
422 return true;
423#endif
Simon Pilgrima271c542017-05-03 15:42:29 +0000424#elif defined(_MSC_VER)
425 int registers[4];
426 __cpuidex(registers, value, subleaf);
427 *rEAX = registers[0];
428 *rEBX = registers[1];
429 *rECX = registers[2];
430 *rEDX = registers[3];
Craig Topper1efd10a2017-07-10 06:04:11 +0000431 return false;
432#else
433 return true;
Simon Pilgrima271c542017-05-03 15:42:29 +0000434#endif
Simon Pilgrima271c542017-05-03 15:42:29 +0000435}
436
Craig Topperf3af64e2017-07-12 06:49:57 +0000437// Read control register 0 (XCR0). Used to detect features such as AVX.
Simon Pilgrima271c542017-05-03 15:42:29 +0000438static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
439#if defined(__GNUC__) || defined(__clang__)
440 // Check xgetbv; this uses a .byte sequence instead of the instruction
441 // directly because older assemblers do not include support for xgetbv and
442 // there is no easy way to conditionally compile based on the assembler used.
443 __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
444 return false;
445#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
446 unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
447 *rEAX = Result;
448 *rEDX = Result >> 32;
449 return false;
450#else
451 return true;
452#endif
453}
454
455static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
456 unsigned *Model) {
457 *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
458 *Model = (EAX >> 4) & 0xf; // Bits 4 - 7
459 if (*Family == 6 || *Family == 0xf) {
460 if (*Family == 0xf)
461 // Examine extended family ID if family ID is F.
462 *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
463 // Examine extended model ID if family ID is 6 or F.
464 *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
465 }
466}
467
468static void
Craig Topperc6bbe4b2017-07-08 05:16:14 +0000469getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
470 unsigned Brand_id, unsigned Features,
Craig Topper3a5d0822017-07-12 06:49:58 +0000471 unsigned Features2, unsigned *Type,
472 unsigned *Subtype) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000473 if (Brand_id != 0)
474 return;
475 switch (Family) {
476 case 3:
Craig Topperc77d00e2017-11-10 17:10:57 +0000477 *Type = X86::INTEL_i386;
Simon Pilgrima271c542017-05-03 15:42:29 +0000478 break;
479 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000480 *Type = X86::INTEL_i486;
Simon Pilgrima271c542017-05-03 15:42:29 +0000481 break;
482 case 5:
Craig Topper47c87392017-11-21 23:36:42 +0000483 if (Features & (1 << X86::FEATURE_MMX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000484 *Type = X86::INTEL_PENTIUM_MMX;
Simon Pilgrima271c542017-05-03 15:42:29 +0000485 break;
486 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000487 *Type = X86::INTEL_PENTIUM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000488 break;
489 case 6:
490 switch (Model) {
491 case 0x01: // Pentium Pro processor
Craig Topperc77d00e2017-11-10 17:10:57 +0000492 *Type = X86::INTEL_PENTIUM_PRO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000493 break;
494 case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
495 // model 03
496 case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
497 // model 05, and Intel Celeron processor, model 05
498 case 0x06: // Celeron processor, model 06
Craig Topperc77d00e2017-11-10 17:10:57 +0000499 *Type = X86::INTEL_PENTIUM_II;
Simon Pilgrima271c542017-05-03 15:42:29 +0000500 break;
501 case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
502 // processor, model 07
503 case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
504 // model 08, and Celeron processor, model 08
505 case 0x0a: // Pentium III Xeon processor, model 0Ah
506 case 0x0b: // Pentium III processor, model 0Bh
Craig Topperc77d00e2017-11-10 17:10:57 +0000507 *Type = X86::INTEL_PENTIUM_III;
Simon Pilgrima271c542017-05-03 15:42:29 +0000508 break;
509 case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
510 case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
511 // 0Dh. All processors are manufactured using the 90 nm process.
512 case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
513 // Integrated Processor with Intel QuickAssist Technology
Craig Topperc77d00e2017-11-10 17:10:57 +0000514 *Type = X86::INTEL_PENTIUM_M;
Simon Pilgrima271c542017-05-03 15:42:29 +0000515 break;
516 case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
517 // 0Eh. All processors are manufactured using the 65 nm process.
Craig Topperc77d00e2017-11-10 17:10:57 +0000518 *Type = X86::INTEL_CORE_DUO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000519 break; // yonah
520 case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
521 // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
522 // mobile processor, Intel Core 2 Extreme processor, Intel
523 // Pentium Dual-Core processor, Intel Xeon processor, model
524 // 0Fh. All processors are manufactured using the 65 nm process.
525 case 0x16: // Intel Celeron processor model 16h. All processors are
526 // manufactured using the 65 nm process
Craig Topperc77d00e2017-11-10 17:10:57 +0000527 *Type = X86::INTEL_CORE2; // "core2"
528 *Subtype = X86::INTEL_CORE2_65;
Simon Pilgrima271c542017-05-03 15:42:29 +0000529 break;
530 case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
531 // 17h. All processors are manufactured using the 45 nm process.
532 //
533 // 45nm: Penryn , Wolfdale, Yorkfield (XE)
534 case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
535 // the 45 nm process.
Craig Topperc77d00e2017-11-10 17:10:57 +0000536 *Type = X86::INTEL_CORE2; // "penryn"
537 *Subtype = X86::INTEL_CORE2_45;
Simon Pilgrima271c542017-05-03 15:42:29 +0000538 break;
539 case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
540 // processors are manufactured using the 45 nm process.
541 case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
542 // As found in a Summer 2010 model iMac.
543 case 0x1f:
544 case 0x2e: // Nehalem EX
Craig Topperc77d00e2017-11-10 17:10:57 +0000545 *Type = X86::INTEL_COREI7; // "nehalem"
546 *Subtype = X86::INTEL_COREI7_NEHALEM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000547 break;
548 case 0x25: // Intel Core i7, laptop version.
549 case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
550 // processors are manufactured using the 32 nm process.
551 case 0x2f: // Westmere EX
Craig Topperc77d00e2017-11-10 17:10:57 +0000552 *Type = X86::INTEL_COREI7; // "westmere"
553 *Subtype = X86::INTEL_COREI7_WESTMERE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000554 break;
555 case 0x2a: // Intel Core i7 processor. All processors are manufactured
556 // using the 32 nm process.
557 case 0x2d:
Craig Topperc77d00e2017-11-10 17:10:57 +0000558 *Type = X86::INTEL_COREI7; //"sandybridge"
559 *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000560 break;
561 case 0x3a:
562 case 0x3e: // Ivy Bridge EP
Craig Topperc77d00e2017-11-10 17:10:57 +0000563 *Type = X86::INTEL_COREI7; // "ivybridge"
564 *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000565 break;
566
567 // Haswell:
568 case 0x3c:
569 case 0x3f:
570 case 0x45:
571 case 0x46:
Craig Topperc77d00e2017-11-10 17:10:57 +0000572 *Type = X86::INTEL_COREI7; // "haswell"
573 *Subtype = X86::INTEL_COREI7_HASWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000574 break;
575
576 // Broadwell:
577 case 0x3d:
578 case 0x47:
579 case 0x4f:
580 case 0x56:
Craig Topperc77d00e2017-11-10 17:10:57 +0000581 *Type = X86::INTEL_COREI7; // "broadwell"
582 *Subtype = X86::INTEL_COREI7_BROADWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000583 break;
584
585 // Skylake:
586 case 0x4e: // Skylake mobile
587 case 0x5e: // Skylake desktop
588 case 0x8e: // Kaby Lake mobile
589 case 0x9e: // Kaby Lake desktop
Craig Topperc77d00e2017-11-10 17:10:57 +0000590 *Type = X86::INTEL_COREI7; // "skylake"
591 *Subtype = X86::INTEL_COREI7_SKYLAKE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000592 break;
593
594 // Skylake Xeon:
595 case 0x55:
Craig Topperc77d00e2017-11-10 17:10:57 +0000596 *Type = X86::INTEL_COREI7;
597 *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512"
Simon Pilgrima271c542017-05-03 15:42:29 +0000598 break;
599
Craig Topper07491862017-11-15 06:02:42 +0000600 // Cannonlake:
601 case 0x66:
602 *Type = X86::INTEL_COREI7;
603 *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake"
604 break;
605
Simon Pilgrima271c542017-05-03 15:42:29 +0000606 case 0x1c: // Most 45 nm Intel Atom processors
607 case 0x26: // 45 nm Atom Lincroft
608 case 0x27: // 32 nm Atom Medfield
609 case 0x35: // 32 nm Atom Midview
610 case 0x36: // 32 nm Atom Midview
Craig Topperc77d00e2017-11-10 17:10:57 +0000611 *Type = X86::INTEL_BONNELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000612 break; // "bonnell"
613
614 // Atom Silvermont codes from the Intel software optimization guide.
615 case 0x37:
616 case 0x4a:
617 case 0x4d:
618 case 0x5a:
619 case 0x5d:
620 case 0x4c: // really airmont
Craig Topperc77d00e2017-11-10 17:10:57 +0000621 *Type = X86::INTEL_SILVERMONT;
Simon Pilgrima271c542017-05-03 15:42:29 +0000622 break; // "silvermont"
Michael Zuckerman4bcb9c32017-06-29 10:00:33 +0000623 // Goldmont:
Craig Topper0dadfe32017-11-15 06:02:43 +0000624 case 0x5c: // Apollo Lake
625 case 0x5f: // Denverton
626 case 0x7a: // Gemini Lake
Craig Topperc77d00e2017-11-10 17:10:57 +0000627 *Type = X86::INTEL_GOLDMONT;
Michael Zuckerman4bcb9c32017-06-29 10:00:33 +0000628 break; // "goldmont"
Simon Pilgrima271c542017-05-03 15:42:29 +0000629 case 0x57:
Craig Topperc77d00e2017-11-10 17:10:57 +0000630 *Type = X86::INTEL_KNL; // knl
Simon Pilgrima271c542017-05-03 15:42:29 +0000631 break;
Craig Topper5d692912017-10-13 18:10:17 +0000632 case 0x85:
Craig Topperc77d00e2017-11-10 17:10:57 +0000633 *Type = X86::INTEL_KNM; // knm
Craig Topper5d692912017-10-13 18:10:17 +0000634 break;
Simon Pilgrima271c542017-05-03 15:42:29 +0000635
636 default: // Unknown family 6 CPU, try to guess.
Craig Topper47c87392017-11-21 23:36:42 +0000637 if (Features & (1 << X86::FEATURE_AVX512VBMI)) {
Craig Topper07491862017-11-15 06:02:42 +0000638 *Type = X86::INTEL_COREI7;
639 *Subtype = X86::INTEL_COREI7_CANNONLAKE;
Craig Topper4eda7562017-07-27 03:26:52 +0000640 break;
641 }
Craig Topper07491862017-11-15 06:02:42 +0000642
Craig Topper47c87392017-11-21 23:36:42 +0000643 if (Features & (1 << X86::FEATURE_AVX512VL)) {
Craig Topper07491862017-11-15 06:02:42 +0000644 *Type = X86::INTEL_COREI7;
645 *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
646 break;
647 }
648
Craig Topper47c87392017-11-21 23:36:42 +0000649 if (Features & (1 << X86::FEATURE_AVX512ER)) {
Craig Topper07491862017-11-15 06:02:42 +0000650 *Type = X86::INTEL_KNL; // knl
651 break;
652 }
653
Craig Topper47c87392017-11-21 23:36:42 +0000654 if (Features2 & (1 << (X86::FEATURE_CLFLUSHOPT - 32))) {
655 if (Features2 & (1 << (X86::FEATURE_SHA - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000656 *Type = X86::INTEL_GOLDMONT;
Craig Topper4eda7562017-07-27 03:26:52 +0000657 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000658 *Type = X86::INTEL_COREI7;
659 *Subtype = X86::INTEL_COREI7_SKYLAKE;
Craig Topper4eda7562017-07-27 03:26:52 +0000660 }
Simon Pilgrima271c542017-05-03 15:42:29 +0000661 break;
662 }
Craig Topper47c87392017-11-21 23:36:42 +0000663 if (Features2 & (1 << (X86::FEATURE_ADX - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000664 *Type = X86::INTEL_COREI7;
665 *Subtype = X86::INTEL_COREI7_BROADWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000666 break;
667 }
Craig Topper47c87392017-11-21 23:36:42 +0000668 if (Features & (1 << X86::FEATURE_AVX2)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000669 *Type = X86::INTEL_COREI7;
670 *Subtype = X86::INTEL_COREI7_HASWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000671 break;
672 }
Craig Topper47c87392017-11-21 23:36:42 +0000673 if (Features & (1 << X86::FEATURE_AVX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000674 *Type = X86::INTEL_COREI7;
675 *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000676 break;
677 }
Craig Topper47c87392017-11-21 23:36:42 +0000678 if (Features & (1 << X86::FEATURE_SSE4_2)) {
679 if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000680 *Type = X86::INTEL_SILVERMONT;
Simon Pilgrima271c542017-05-03 15:42:29 +0000681 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000682 *Type = X86::INTEL_COREI7;
683 *Subtype = X86::INTEL_COREI7_NEHALEM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000684 }
685 break;
686 }
Craig Topper47c87392017-11-21 23:36:42 +0000687 if (Features & (1 << X86::FEATURE_SSE4_1)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000688 *Type = X86::INTEL_CORE2; // "penryn"
689 *Subtype = X86::INTEL_CORE2_45;
Simon Pilgrima271c542017-05-03 15:42:29 +0000690 break;
691 }
Craig Topper47c87392017-11-21 23:36:42 +0000692 if (Features & (1 << X86::FEATURE_SSSE3)) {
693 if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000694 *Type = X86::INTEL_BONNELL; // "bonnell"
Simon Pilgrima271c542017-05-03 15:42:29 +0000695 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000696 *Type = X86::INTEL_CORE2; // "core2"
697 *Subtype = X86::INTEL_CORE2_65;
Simon Pilgrima271c542017-05-03 15:42:29 +0000698 }
699 break;
700 }
Craig Topper47c87392017-11-21 23:36:42 +0000701 if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000702 *Type = X86::INTEL_CORE2; // "core2"
703 *Subtype = X86::INTEL_CORE2_65;
Craig Toppera233e162017-11-02 19:13:32 +0000704 break;
705 }
Craig Topper47c87392017-11-21 23:36:42 +0000706 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000707 *Type = X86::INTEL_CORE_DUO;
Craig Toppera233e162017-11-02 19:13:32 +0000708 break;
Simon Pilgrima271c542017-05-03 15:42:29 +0000709 }
Craig Topper47c87392017-11-21 23:36:42 +0000710 if (Features & (1 << X86::FEATURE_SSE2)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000711 *Type = X86::INTEL_PENTIUM_M;
Simon Pilgrima271c542017-05-03 15:42:29 +0000712 break;
713 }
Craig Topper47c87392017-11-21 23:36:42 +0000714 if (Features & (1 << X86::FEATURE_SSE)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000715 *Type = X86::INTEL_PENTIUM_III;
Simon Pilgrima271c542017-05-03 15:42:29 +0000716 break;
717 }
Craig Topper47c87392017-11-21 23:36:42 +0000718 if (Features & (1 << X86::FEATURE_MMX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000719 *Type = X86::INTEL_PENTIUM_II;
Simon Pilgrima271c542017-05-03 15:42:29 +0000720 break;
721 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000722 *Type = X86::INTEL_PENTIUM_PRO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000723 break;
724 }
725 break;
726 case 15: {
Craig Topper47c87392017-11-21 23:36:42 +0000727 if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000728 *Type = X86::INTEL_NOCONA;
Simon Pilgrima271c542017-05-03 15:42:29 +0000729 break;
730 }
Craig Topper47c87392017-11-21 23:36:42 +0000731 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000732 *Type = X86::INTEL_PRESCOTT;
Craig Topper14949152017-11-02 19:13:34 +0000733 break;
734 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000735 *Type = X86::INTEL_PENTIUM_IV;
Simon Pilgrima271c542017-05-03 15:42:29 +0000736 break;
737 }
738 default:
739 break; /*"generic"*/
740 }
741}
742
Craig Topper2ace1532017-07-08 06:44:34 +0000743static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
744 unsigned Features, unsigned *Type,
Simon Pilgrima271c542017-05-03 15:42:29 +0000745 unsigned *Subtype) {
746 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
747 // appears to be no way to generate the wide variety of AMD-specific targets
748 // from the information returned from CPUID.
749 switch (Family) {
750 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000751 *Type = X86::AMD_i486;
Simon Pilgrima271c542017-05-03 15:42:29 +0000752 break;
753 case 5:
Craig Topperc77d00e2017-11-10 17:10:57 +0000754 *Type = X86::AMDPENTIUM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000755 switch (Model) {
756 case 6:
757 case 7:
Craig Topperc77d00e2017-11-10 17:10:57 +0000758 *Subtype = X86::AMDPENTIUM_K6;
Simon Pilgrima271c542017-05-03 15:42:29 +0000759 break; // "k6"
760 case 8:
Craig Topperc77d00e2017-11-10 17:10:57 +0000761 *Subtype = X86::AMDPENTIUM_K62;
Simon Pilgrima271c542017-05-03 15:42:29 +0000762 break; // "k6-2"
763 case 9:
764 case 13:
Craig Topperc77d00e2017-11-10 17:10:57 +0000765 *Subtype = X86::AMDPENTIUM_K63;
Simon Pilgrima271c542017-05-03 15:42:29 +0000766 break; // "k6-3"
767 case 10:
Craig Topperc77d00e2017-11-10 17:10:57 +0000768 *Subtype = X86::AMDPENTIUM_GEODE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000769 break; // "geode"
770 }
771 break;
772 case 6:
Craig Topper47c87392017-11-21 23:36:42 +0000773 if (Features & (1 << X86::FEATURE_SSE)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000774 *Type = X86::AMD_ATHLON_XP;
Simon Pilgrima271c542017-05-03 15:42:29 +0000775 break; // "athlon-xp"
776 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000777 *Type = X86::AMD_ATHLON;
Craig Topperf3de5eb2017-07-13 06:34:10 +0000778 break; // "athlon"
Simon Pilgrima271c542017-05-03 15:42:29 +0000779 case 15:
Craig Topper47c87392017-11-21 23:36:42 +0000780 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000781 *Type = X86::AMD_K8SSE3;
Simon Pilgrima271c542017-05-03 15:42:29 +0000782 break; // "k8-sse3"
783 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000784 *Type = X86::AMD_K8;
Craig Topperf3de5eb2017-07-13 06:34:10 +0000785 break; // "k8"
Simon Pilgrima271c542017-05-03 15:42:29 +0000786 case 16:
Craig Topperc77d00e2017-11-10 17:10:57 +0000787 *Type = X86::AMDFAM10H; // "amdfam10"
Simon Pilgrima271c542017-05-03 15:42:29 +0000788 switch (Model) {
789 case 2:
Craig Topperc77d00e2017-11-10 17:10:57 +0000790 *Subtype = X86::AMDFAM10H_BARCELONA;
Simon Pilgrima271c542017-05-03 15:42:29 +0000791 break;
792 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000793 *Subtype = X86::AMDFAM10H_SHANGHAI;
Simon Pilgrima271c542017-05-03 15:42:29 +0000794 break;
795 case 8:
Craig Topperc77d00e2017-11-10 17:10:57 +0000796 *Subtype = X86::AMDFAM10H_ISTANBUL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000797 break;
798 }
799 break;
800 case 20:
Craig Topperc77d00e2017-11-10 17:10:57 +0000801 *Type = X86::AMD_BTVER1;
Simon Pilgrima271c542017-05-03 15:42:29 +0000802 break; // "btver1";
803 case 21:
Craig Topperc77d00e2017-11-10 17:10:57 +0000804 *Type = X86::AMDFAM15H;
Craig Topper1f9d3c02017-07-08 06:44:35 +0000805 if (Model >= 0x60 && Model <= 0x7f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000806 *Subtype = X86::AMDFAM15H_BDVER4;
Craig Topper3db11702017-07-12 06:49:56 +0000807 break; // "bdver4"; 60h-7Fh: Excavator
Simon Pilgrima271c542017-05-03 15:42:29 +0000808 }
809 if (Model >= 0x30 && Model <= 0x3f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000810 *Subtype = X86::AMDFAM15H_BDVER3;
Simon Pilgrima271c542017-05-03 15:42:29 +0000811 break; // "bdver3"; 30h-3Fh: Steamroller
812 }
813 if (Model >= 0x10 && Model <= 0x1f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000814 *Subtype = X86::AMDFAM15H_BDVER2;
Simon Pilgrima271c542017-05-03 15:42:29 +0000815 break; // "bdver2"; 10h-1Fh: Piledriver
816 }
817 if (Model <= 0x0f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000818 *Subtype = X86::AMDFAM15H_BDVER1;
Simon Pilgrima271c542017-05-03 15:42:29 +0000819 break; // "bdver1"; 00h-0Fh: Bulldozer
820 }
821 break;
822 case 22:
Craig Topperc77d00e2017-11-10 17:10:57 +0000823 *Type = X86::AMD_BTVER2;
Simon Pilgrima271c542017-05-03 15:42:29 +0000824 break; // "btver2"
825 case 23:
Craig Topperc77d00e2017-11-10 17:10:57 +0000826 *Type = X86::AMDFAM17H;
827 *Subtype = X86::AMDFAM17H_ZNVER1;
Simon Pilgrima271c542017-05-03 15:42:29 +0000828 break;
829 default:
830 break; // "generic"
831 }
832}
833
Craig Topper3a5d0822017-07-12 06:49:58 +0000834static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
835 unsigned *FeaturesOut,
836 unsigned *Features2Out) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000837 unsigned Features = 0;
Craig Topper3a5d0822017-07-12 06:49:58 +0000838 unsigned Features2 = 0;
Craig Topperc6bbe4b2017-07-08 05:16:14 +0000839 unsigned EAX, EBX;
Craig Topper3a5d0822017-07-12 06:49:58 +0000840
841 if ((EDX >> 15) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000842 Features |= 1 << X86::FEATURE_CMOV;
Craig Topper3a5d0822017-07-12 06:49:58 +0000843 if ((EDX >> 23) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000844 Features |= 1 << X86::FEATURE_MMX;
Craig Topper3a5d0822017-07-12 06:49:58 +0000845 if ((EDX >> 25) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000846 Features |= 1 << X86::FEATURE_SSE;
Craig Topper3a5d0822017-07-12 06:49:58 +0000847 if ((EDX >> 26) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000848 Features |= 1 << X86::FEATURE_SSE2;
Craig Topper3a5d0822017-07-12 06:49:58 +0000849
850 if ((ECX >> 0) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000851 Features |= 1 << X86::FEATURE_SSE3;
Craig Topper3a5d0822017-07-12 06:49:58 +0000852 if ((ECX >> 1) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000853 Features |= 1 << X86::FEATURE_PCLMUL;
Craig Topper3a5d0822017-07-12 06:49:58 +0000854 if ((ECX >> 9) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000855 Features |= 1 << X86::FEATURE_SSSE3;
Craig Topper3a5d0822017-07-12 06:49:58 +0000856 if ((ECX >> 12) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000857 Features |= 1 << X86::FEATURE_FMA;
Craig Topper3a5d0822017-07-12 06:49:58 +0000858 if ((ECX >> 19) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000859 Features |= 1 << X86::FEATURE_SSE4_1;
Craig Topper3a5d0822017-07-12 06:49:58 +0000860 if ((ECX >> 20) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000861 Features |= 1 << X86::FEATURE_SSE4_2;
Craig Topper3a5d0822017-07-12 06:49:58 +0000862 if ((ECX >> 23) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000863 Features |= 1 << X86::FEATURE_POPCNT;
Craig Topper3a5d0822017-07-12 06:49:58 +0000864 if ((ECX >> 25) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000865 Features |= 1 << X86::FEATURE_AES;
Craig Topper3a5d0822017-07-12 06:49:58 +0000866
867 if ((ECX >> 22) & 1)
Craig Topper47c87392017-11-21 23:36:42 +0000868 Features2 |= 1 << (X86::FEATURE_MOVBE - 32);
Simon Pilgrima271c542017-05-03 15:42:29 +0000869
870 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
871 // indicates that the AVX registers will be saved and restored on context
872 // switch, then we have full AVX support.
873 const unsigned AVXBits = (1 << 27) | (1 << 28);
874 bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
875 ((EAX & 0x6) == 0x6);
876 bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
Craig Topper3a5d0822017-07-12 06:49:58 +0000877
878 if (HasAVX)
Craig Topper47c87392017-11-21 23:36:42 +0000879 Features |= 1 << X86::FEATURE_AVX;
Craig Topper3a5d0822017-07-12 06:49:58 +0000880
Simon Pilgrima271c542017-05-03 15:42:29 +0000881 bool HasLeaf7 =
882 MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
Craig Topper3a5d0822017-07-12 06:49:58 +0000883
884 if (HasLeaf7 && ((EBX >> 3) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000885 Features |= 1 << X86::FEATURE_BMI;
Craig Topper3a5d0822017-07-12 06:49:58 +0000886 if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
Craig Topper47c87392017-11-21 23:36:42 +0000887 Features |= 1 << X86::FEATURE_AVX2;
Craig Topper3a5d0822017-07-12 06:49:58 +0000888 if (HasLeaf7 && ((EBX >> 9) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000889 Features |= 1 << X86::FEATURE_BMI2;
Craig Topper3a5d0822017-07-12 06:49:58 +0000890 if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000891 Features |= 1 << X86::FEATURE_AVX512F;
Craig Topper3a5d0822017-07-12 06:49:58 +0000892 if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000893 Features |= 1 << X86::FEATURE_AVX512DQ;
Craig Topper3a5d0822017-07-12 06:49:58 +0000894 if (HasLeaf7 && ((EBX >> 19) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000895 Features2 |= 1 << (X86::FEATURE_ADX - 32);
Craig Topper3a5d0822017-07-12 06:49:58 +0000896 if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000897 Features |= 1 << X86::FEATURE_AVX512IFMA;
Craig Topper4eda7562017-07-27 03:26:52 +0000898 if (HasLeaf7 && ((EBX >> 23) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000899 Features2 |= 1 << (X86::FEATURE_CLFLUSHOPT - 32);
Craig Topper3a5d0822017-07-12 06:49:58 +0000900 if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000901 Features |= 1 << X86::FEATURE_AVX512PF;
Craig Topper3a5d0822017-07-12 06:49:58 +0000902 if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000903 Features |= 1 << X86::FEATURE_AVX512ER;
Craig Topper3a5d0822017-07-12 06:49:58 +0000904 if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000905 Features |= 1 << X86::FEATURE_AVX512CD;
Craig Topper4eda7562017-07-27 03:26:52 +0000906 if (HasLeaf7 && ((EBX >> 29) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000907 Features2 |= 1 << (X86::FEATURE_SHA - 32);
Craig Topper3a5d0822017-07-12 06:49:58 +0000908 if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000909 Features |= 1 << X86::FEATURE_AVX512BW;
Craig Topper3a5d0822017-07-12 06:49:58 +0000910 if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000911 Features |= 1 << X86::FEATURE_AVX512VL;
Craig Topper3a5d0822017-07-12 06:49:58 +0000912
913 if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000914 Features |= 1 << X86::FEATURE_AVX512VBMI;
Craig Topper3a5d0822017-07-12 06:49:58 +0000915 if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000916 Features |= 1 << X86::FEATURE_AVX512VPOPCNTDQ;
Craig Topper3a5d0822017-07-12 06:49:58 +0000917
918 if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000919 Features |= 1 << X86::FEATURE_AVX5124VNNIW;
Craig Topper3a5d0822017-07-12 06:49:58 +0000920 if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
Craig Topper47c87392017-11-21 23:36:42 +0000921 Features |= 1 << X86::FEATURE_AVX5124FMAPS;
Simon Pilgrima271c542017-05-03 15:42:29 +0000922
Craig Topperbb8c7992017-07-08 05:16:13 +0000923 unsigned MaxExtLevel;
924 getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
925
926 bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
927 !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
Craig Topper3a5d0822017-07-12 06:49:58 +0000928 if (HasExtLeaf1 && ((ECX >> 6) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000929 Features |= 1 << X86::FEATURE_SSE4_A;
Craig Topper3a5d0822017-07-12 06:49:58 +0000930 if (HasExtLeaf1 && ((ECX >> 11) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000931 Features |= 1 << X86::FEATURE_XOP;
Craig Topper3a5d0822017-07-12 06:49:58 +0000932 if (HasExtLeaf1 && ((ECX >> 16) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000933 Features |= 1 << X86::FEATURE_FMA4;
Craig Topperbb8c7992017-07-08 05:16:13 +0000934
Craig Topper3a5d0822017-07-12 06:49:58 +0000935 if (HasExtLeaf1 && ((EDX >> 29) & 1))
Craig Topper47c87392017-11-21 23:36:42 +0000936 Features2 |= 1 << (X86::FEATURE_EM64T - 32);
Craig Topper3a5d0822017-07-12 06:49:58 +0000937
938 *FeaturesOut = Features;
939 *Features2Out = Features2;
Simon Pilgrima271c542017-05-03 15:42:29 +0000940}
941
942StringRef sys::getHostCPUName() {
943 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
944 unsigned MaxLeaf, Vendor;
945
946#if defined(__GNUC__) || defined(__clang__)
947 //FIXME: include cpuid.h from clang or copy __get_cpuid_max here
948 // and simplify it to not invoke __cpuid (like cpu_model.c in
949 // compiler-rt/lib/builtins/cpu_model.c?
950 // Opting for the second option.
951 if(!isCpuIdSupported())
952 return "generic";
953#endif
Craig Topperbb8c7992017-07-08 05:16:13 +0000954 if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1)
Simon Pilgrima271c542017-05-03 15:42:29 +0000955 return "generic";
Craig Topperbb8c7992017-07-08 05:16:13 +0000956 getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
Simon Pilgrima271c542017-05-03 15:42:29 +0000957
958 unsigned Brand_id = EBX & 0xff;
959 unsigned Family = 0, Model = 0;
Craig Topper3a5d0822017-07-12 06:49:58 +0000960 unsigned Features = 0, Features2 = 0;
Simon Pilgrima271c542017-05-03 15:42:29 +0000961 detectX86FamilyModel(EAX, &Family, &Model);
Craig Topper3a5d0822017-07-12 06:49:58 +0000962 getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2);
Simon Pilgrima271c542017-05-03 15:42:29 +0000963
Craig Topper741e7e62017-11-03 18:02:44 +0000964 unsigned Type = 0;
965 unsigned Subtype = 0;
Simon Pilgrima271c542017-05-03 15:42:29 +0000966
967 if (Vendor == SIG_INTEL) {
Craig Topper3a5d0822017-07-12 06:49:58 +0000968 getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features,
969 Features2, &Type, &Subtype);
Simon Pilgrima271c542017-05-03 15:42:29 +0000970 } else if (Vendor == SIG_AMD) {
971 getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
Simon Pilgrima271c542017-05-03 15:42:29 +0000972 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000973
974 // Check subtypes first since those are more specific.
975#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
976 if (Subtype == X86::ENUM) \
977 return ARCHNAME;
978#include "llvm/Support/X86TargetParser.def"
979
980 // Now check types.
981#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
982 if (Type == X86::ENUM) \
983 return ARCHNAME;
984#include "llvm/Support/X86TargetParser.def"
985
Simon Pilgrima271c542017-05-03 15:42:29 +0000986 return "generic";
987}
988
989#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
990StringRef sys::getHostCPUName() {
991 host_basic_info_data_t hostInfo;
992 mach_msg_type_number_t infoCount;
993
994 infoCount = HOST_BASIC_INFO_COUNT;
995 host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
996 &infoCount);
997
998 if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
999 return "generic";
1000
1001 switch (hostInfo.cpu_subtype) {
1002 case CPU_SUBTYPE_POWERPC_601:
1003 return "601";
1004 case CPU_SUBTYPE_POWERPC_602:
1005 return "602";
1006 case CPU_SUBTYPE_POWERPC_603:
1007 return "603";
1008 case CPU_SUBTYPE_POWERPC_603e:
1009 return "603e";
1010 case CPU_SUBTYPE_POWERPC_603ev:
1011 return "603ev";
1012 case CPU_SUBTYPE_POWERPC_604:
1013 return "604";
1014 case CPU_SUBTYPE_POWERPC_604e:
1015 return "604e";
1016 case CPU_SUBTYPE_POWERPC_620:
1017 return "620";
1018 case CPU_SUBTYPE_POWERPC_750:
1019 return "750";
1020 case CPU_SUBTYPE_POWERPC_7400:
1021 return "7400";
1022 case CPU_SUBTYPE_POWERPC_7450:
1023 return "7450";
1024 case CPU_SUBTYPE_POWERPC_970:
1025 return "970";
1026 default:;
1027 }
1028
1029 return "generic";
1030}
1031#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
1032StringRef sys::getHostCPUName() {
1033 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1034 const StringRef& Content = P ? P->getBuffer() : "";
1035 return detail::getHostCPUNameForPowerPC(Content);
1036}
1037#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1038StringRef sys::getHostCPUName() {
1039 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1040 const StringRef& Content = P ? P->getBuffer() : "";
1041 return detail::getHostCPUNameForARM(Content);
1042}
1043#elif defined(__linux__) && defined(__s390x__)
1044StringRef sys::getHostCPUName() {
1045 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1046 const StringRef& Content = P ? P->getBuffer() : "";
1047 return detail::getHostCPUNameForS390x(Content);
1048}
1049#else
1050StringRef sys::getHostCPUName() { return "generic"; }
1051#endif
1052
1053#if defined(__linux__) && defined(__x86_64__)
1054// On Linux, the number of physical cores can be computed from /proc/cpuinfo,
1055// using the number of unique physical/core id pairs. The following
1056// implementation reads the /proc/cpuinfo format on an x86_64 system.
1057static int computeHostNumPhysicalCores() {
1058 // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be
1059 // mmapped because it appears to have 0 size.
1060 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
1061 llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
1062 if (std::error_code EC = Text.getError()) {
1063 llvm::errs() << "Can't read "
1064 << "/proc/cpuinfo: " << EC.message() << "\n";
1065 return -1;
1066 }
1067 SmallVector<StringRef, 8> strs;
1068 (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
1069 /*KeepEmpty=*/false);
1070 int CurPhysicalId = -1;
1071 int CurCoreId = -1;
1072 SmallSet<std::pair<int, int>, 32> UniqueItems;
1073 for (auto &Line : strs) {
1074 Line = Line.trim();
1075 if (!Line.startswith("physical id") && !Line.startswith("core id"))
1076 continue;
1077 std::pair<StringRef, StringRef> Data = Line.split(':');
1078 auto Name = Data.first.trim();
1079 auto Val = Data.second.trim();
1080 if (Name == "physical id") {
1081 assert(CurPhysicalId == -1 &&
1082 "Expected a core id before seeing another physical id");
1083 Val.getAsInteger(10, CurPhysicalId);
1084 }
1085 if (Name == "core id") {
1086 assert(CurCoreId == -1 &&
1087 "Expected a physical id before seeing another core id");
1088 Val.getAsInteger(10, CurCoreId);
1089 }
1090 if (CurPhysicalId != -1 && CurCoreId != -1) {
1091 UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
1092 CurPhysicalId = -1;
1093 CurCoreId = -1;
1094 }
1095 }
1096 return UniqueItems.size();
1097}
1098#elif defined(__APPLE__) && defined(__x86_64__)
1099#include <sys/param.h>
1100#include <sys/sysctl.h>
1101
1102// Gets the number of *physical cores* on the machine.
1103static int computeHostNumPhysicalCores() {
1104 uint32_t count;
1105 size_t len = sizeof(count);
1106 sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
1107 if (count < 1) {
1108 int nm[2];
1109 nm[0] = CTL_HW;
1110 nm[1] = HW_AVAILCPU;
1111 sysctl(nm, 2, &count, &len, NULL, 0);
1112 if (count < 1)
1113 return -1;
1114 }
1115 return count;
1116}
1117#else
1118// On other systems, return -1 to indicate unknown.
1119static int computeHostNumPhysicalCores() { return -1; }
1120#endif
1121
1122int sys::getHostNumPhysicalCores() {
1123 static int NumCores = computeHostNumPhysicalCores();
1124 return NumCores;
1125}
1126
1127#if defined(__i386__) || defined(_M_IX86) || \
1128 defined(__x86_64__) || defined(_M_X64)
1129bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1130 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1131 unsigned MaxLevel;
1132 union {
1133 unsigned u[3];
1134 char c[12];
1135 } text;
1136
1137 if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
1138 MaxLevel < 1)
1139 return false;
1140
1141 getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1142
Craig Topper1af7e442017-11-19 23:30:22 +00001143 Features["cmov"] = (EDX >> 15) & 1;
1144 Features["mmx"] = (EDX >> 23) & 1;
1145 Features["sse"] = (EDX >> 25) & 1;
1146 Features["sse2"] = (EDX >> 26) & 1;
1147
1148 Features["sse3"] = (ECX >> 0) & 1;
1149 Features["pclmul"] = (ECX >> 1) & 1;
1150 Features["ssse3"] = (ECX >> 9) & 1;
1151 Features["cx16"] = (ECX >> 13) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001152 Features["sse4.1"] = (ECX >> 19) & 1;
1153 Features["sse4.2"] = (ECX >> 20) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001154 Features["movbe"] = (ECX >> 22) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001155 Features["popcnt"] = (ECX >> 23) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001156 Features["aes"] = (ECX >> 25) & 1;
1157 Features["rdrnd"] = (ECX >> 30) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001158
1159 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1160 // indicates that the AVX registers will be saved and restored on context
1161 // switch, then we have full AVX support.
1162 bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
1163 !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
Simon Pilgrima271c542017-05-03 15:42:29 +00001164 // AVX512 requires additional context to be saved by the OS.
1165 bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1166
Craig Topper1af7e442017-11-19 23:30:22 +00001167 Features["avx"] = HasAVXSave;
1168 Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;
1169 // Only enable XSAVE if OS has enabled support for saving YMM state.
1170 Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1171 Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave;
1172
Simon Pilgrima271c542017-05-03 15:42:29 +00001173 unsigned MaxExtLevel;
1174 getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1175
1176 bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1177 !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
Craig Topper1af7e442017-11-19 23:30:22 +00001178 Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
1179 Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
1180 Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
1181 Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1182 Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1);
1183 Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1184 Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001185 Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1186
1187 bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
Craig Topperdcd69792017-11-19 23:49:19 +00001188 !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
Simon Pilgrima271c542017-05-03 15:42:29 +00001189 Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1);
1190
1191 bool HasLeaf7 =
1192 MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1193
Craig Topper1af7e442017-11-19 23:30:22 +00001194 Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
1195 Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);
1196 Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001197 // AVX2 is only supported if we have the OS save support from AVX.
Craig Topper1af7e442017-11-19 23:30:22 +00001198 Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave;
1199 Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
1200 Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001201 // AVX512 is only supported if the OS supports the context save for it.
Craig Topper1af7e442017-11-19 23:30:22 +00001202 Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1203 Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1204 Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
1205 Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001206 Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
Craig Topper1af7e442017-11-19 23:30:22 +00001207 Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1208 Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);
1209 Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
1210 Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
1211 Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1212 Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
1213 Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1214 Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
Simon Pilgrima271c542017-05-03 15:42:29 +00001215
Craig Topper1af7e442017-11-19 23:30:22 +00001216 Features["prefetchwt1"] = HasLeaf7 && ((ECX >> 0) & 1);
1217 Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;
Craig Topper9b03f672017-11-21 18:50:41 +00001218 Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
Coby Tayree71e37cc2017-11-21 09:48:44 +00001219 Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save;
Coby Tayreed8b17be2017-11-26 09:36:41 +00001220 Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1);
Craig Topper9b03f672017-11-21 18:50:41 +00001221 Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave;
1222 Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1223 Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1224 Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
Yonghong Songdc1dbf62017-08-23 04:25:57 +00001225 Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
Coby Tayree5c7fe5d2017-11-21 10:32:42 +00001226
Simon Pilgrima271c542017-05-03 15:42:29 +00001227 bool HasLeafD = MaxLevel >= 0xd &&
1228 !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1229
1230 // Only enable XSAVE if OS has enabled support for saving YMM state.
Craig Topper1af7e442017-11-19 23:30:22 +00001231 Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1232 Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1233 Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
Simon Pilgrima271c542017-05-03 15:42:29 +00001234
1235 return true;
1236}
1237#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1238bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1239 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1240 if (!P)
1241 return false;
1242
1243 SmallVector<StringRef, 32> Lines;
1244 P->getBuffer().split(Lines, "\n");
1245
1246 SmallVector<StringRef, 32> CPUFeatures;
1247
1248 // Look for the CPU features.
1249 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
1250 if (Lines[I].startswith("Features")) {
1251 Lines[I].split(CPUFeatures, ' ');
1252 break;
1253 }
1254
1255#if defined(__aarch64__)
1256 // Keep track of which crypto features we have seen
1257 enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
1258 uint32_t crypto = 0;
1259#endif
1260
1261 for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
1262 StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
1263#if defined(__aarch64__)
1264 .Case("asimd", "neon")
1265 .Case("fp", "fp-armv8")
1266 .Case("crc32", "crc")
1267#else
1268 .Case("half", "fp16")
1269 .Case("neon", "neon")
1270 .Case("vfpv3", "vfp3")
1271 .Case("vfpv3d16", "d16")
1272 .Case("vfpv4", "vfp4")
1273 .Case("idiva", "hwdiv-arm")
1274 .Case("idivt", "hwdiv")
1275#endif
1276 .Default("");
1277
1278#if defined(__aarch64__)
1279 // We need to check crypto separately since we need all of the crypto
1280 // extensions to enable the subtarget feature
1281 if (CPUFeatures[I] == "aes")
1282 crypto |= CAP_AES;
1283 else if (CPUFeatures[I] == "pmull")
1284 crypto |= CAP_PMULL;
1285 else if (CPUFeatures[I] == "sha1")
1286 crypto |= CAP_SHA1;
1287 else if (CPUFeatures[I] == "sha2")
1288 crypto |= CAP_SHA2;
1289#endif
1290
1291 if (LLVMFeatureStr != "")
1292 Features[LLVMFeatureStr] = true;
1293 }
1294
1295#if defined(__aarch64__)
1296 // If we have all crypto bits we can add the feature
1297 if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
1298 Features["crypto"] = true;
1299#endif
1300
1301 return true;
1302}
1303#else
1304bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
1305#endif
1306
1307std::string sys::getProcessTriple() {
Alex Lorenz3803df32017-07-07 09:53:47 +00001308 std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
1309 Triple PT(Triple::normalize(TargetTripleString));
Simon Pilgrima271c542017-05-03 15:42:29 +00001310
1311 if (sizeof(void *) == 8 && PT.isArch32Bit())
1312 PT = PT.get64BitArchVariant();
1313 if (sizeof(void *) == 4 && PT.isArch64Bit())
1314 PT = PT.get32BitArchVariant();
1315
1316 return PT.str();
1317}