blob: f23645680648f1fa9008b3a903c85419421cdaed [file] [log] [blame]
Simon Pilgrima271c542017-05-03 15:42:29 +00001//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Simon Pilgrima271c542017-05-03 15:42:29 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the operating system Host concept.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/Host.h"
14#include "llvm/ADT/SmallSet.h"
15#include "llvm/ADT/SmallVector.h"
Reid Kleckner47359fb2020-03-11 15:30:04 -070016#include "llvm/ADT/StringMap.h"
Simon Pilgrima271c542017-05-03 15:42:29 +000017#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/ADT/Triple.h"
Nico Weber432a3882018-04-30 14:59:11 +000020#include "llvm/Config/llvm-config.h"
Simon Pilgrima271c542017-05-03 15:42:29 +000021#include "llvm/Support/Debug.h"
22#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/MemoryBuffer.h"
Reid Kleckner47359fb2020-03-11 15:30:04 -070024#include "llvm/Support/TargetParser.h"
Simon Pilgrima271c542017-05-03 15:42:29 +000025#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
Nico Weber712e8d22018-04-29 00:45:03 +000033#ifdef _WIN32
Simon Pilgrima271c542017-05-03 15:42:29 +000034#include "Windows/Host.inc"
35#endif
36#ifdef _MSC_VER
37#include <intrin.h>
38#endif
Chris Bieneman34688fa2019-10-30 12:50:04 -070039#if defined(__APPLE__) && (!defined(__x86_64__))
Simon Pilgrima271c542017-05-03 15:42:29 +000040#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
Craig Topper8665f592018-03-07 17:53:16 +000068StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
Simon Pilgrima271c542017-05-03 15:42:29 +000069 // Access to the Processor Version Register (PVR) on PowerPC is privileged,
70 // and so we must use an operating-system interface to determine the current
71 // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
72 const char *generic = "generic";
73
74 // The cpu line is second (after the 'processor: 0' line), so if this
75 // buffer is too small then something has changed (or is wrong).
76 StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
77 StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
78
79 StringRef::const_iterator CIP = CPUInfoStart;
80
81 StringRef::const_iterator CPUStart = 0;
82 size_t CPULen = 0;
83
84 // We need to find the first line which starts with cpu, spaces, and a colon.
85 // After the colon, there may be some additional spaces and then the cpu type.
86 while (CIP < CPUInfoEnd && CPUStart == 0) {
87 if (CIP < CPUInfoEnd && *CIP == '\n')
88 ++CIP;
89
90 if (CIP < CPUInfoEnd && *CIP == 'c') {
91 ++CIP;
92 if (CIP < CPUInfoEnd && *CIP == 'p') {
93 ++CIP;
94 if (CIP < CPUInfoEnd && *CIP == 'u') {
95 ++CIP;
96 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
97 ++CIP;
98
99 if (CIP < CPUInfoEnd && *CIP == ':') {
100 ++CIP;
101 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
102 ++CIP;
103
104 if (CIP < CPUInfoEnd) {
105 CPUStart = CIP;
106 while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
107 *CIP != ',' && *CIP != '\n'))
108 ++CIP;
109 CPULen = CIP - CPUStart;
110 }
111 }
112 }
113 }
114 }
115
116 if (CPUStart == 0)
117 while (CIP < CPUInfoEnd && *CIP != '\n')
118 ++CIP;
119 }
120
121 if (CPUStart == 0)
122 return generic;
123
124 return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
125 .Case("604e", "604e")
126 .Case("604", "604")
127 .Case("7400", "7400")
128 .Case("7410", "7400")
129 .Case("7447", "7400")
130 .Case("7455", "7450")
131 .Case("G4", "g4")
132 .Case("POWER4", "970")
133 .Case("PPC970FX", "970")
134 .Case("PPC970MP", "970")
135 .Case("G5", "g5")
136 .Case("POWER5", "g5")
137 .Case("A2", "a2")
138 .Case("POWER6", "pwr6")
139 .Case("POWER7", "pwr7")
140 .Case("POWER8", "pwr8")
141 .Case("POWER8E", "pwr8")
142 .Case("POWER8NVL", "pwr8")
143 .Case("POWER9", "pwr9")
Stefan Pintiliedcceab12019-11-27 12:50:23 -0600144 // FIXME: If we get a simulator or machine with the capabilities of
145 // mcpu=future, we should revisit this and add the name reported by the
146 // simulator/machine.
Simon Pilgrima271c542017-05-03 15:42:29 +0000147 .Default(generic);
148}
149
Craig Topper8665f592018-03-07 17:53:16 +0000150StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000151 // The cpuid register on arm is not accessible from user space. On Linux,
152 // it is exposed through the /proc/cpuinfo file.
153
154 // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
155 // in all cases.
156 SmallVector<StringRef, 32> Lines;
157 ProcCpuinfoContent.split(Lines, "\n");
158
159 // Look for the CPU implementer line.
160 StringRef Implementer;
161 StringRef Hardware;
162 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
163 if (Lines[I].startswith("CPU implementer"))
164 Implementer = Lines[I].substr(15).ltrim("\t :");
165 if (Lines[I].startswith("Hardware"))
166 Hardware = Lines[I].substr(8).ltrim("\t :");
167 }
168
169 if (Implementer == "0x41") { // ARM Ltd.
170 // MSM8992/8994 may give cpu part for the core that the kernel is running on,
171 // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
172 if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996"))
173 return "cortex-a53";
174
175
176 // Look for the CPU part line.
177 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
178 if (Lines[I].startswith("CPU part"))
179 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
180 // values correspond to the "Part number" in the CP15/c0 register. The
181 // contents are specified in the various processor manuals.
Luke Geeson4518aab2020-02-11 16:57:25 +0000182 // This corresponds to the Main ID Register in Technical Reference Manuals.
183 // and is used in programs like sys-utils
Simon Pilgrima271c542017-05-03 15:42:29 +0000184 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
185 .Case("0x926", "arm926ej-s")
186 .Case("0xb02", "mpcore")
187 .Case("0xb36", "arm1136j-s")
188 .Case("0xb56", "arm1156t2-s")
189 .Case("0xb76", "arm1176jz-s")
190 .Case("0xc08", "cortex-a8")
191 .Case("0xc09", "cortex-a9")
192 .Case("0xc0f", "cortex-a15")
193 .Case("0xc20", "cortex-m0")
194 .Case("0xc23", "cortex-m3")
195 .Case("0xc24", "cortex-m4")
Luke Geeson7d594cf2020-02-14 13:33:32 +0000196 .Case("0xd22", "cortex-m55")
Luke Geeson4518aab2020-02-11 16:57:25 +0000197 .Case("0xd02", "cortex-a34")
Simon Pilgrima271c542017-05-03 15:42:29 +0000198 .Case("0xd04", "cortex-a35")
199 .Case("0xd03", "cortex-a53")
200 .Case("0xd07", "cortex-a57")
201 .Case("0xd08", "cortex-a72")
202 .Case("0xd09", "cortex-a73")
Yi Kong432f48f2019-06-11 00:05:36 +0000203 .Case("0xd0a", "cortex-a75")
204 .Case("0xd0b", "cortex-a76")
Simon Pilgrima271c542017-05-03 15:42:29 +0000205 .Default("generic");
206 }
207
Joel Jones0a6c0002018-10-05 22:23:21 +0000208 if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
209 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
210 if (Lines[I].startswith("CPU part")) {
211 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
212 .Case("0x516", "thunderx2t99")
213 .Case("0x0516", "thunderx2t99")
214 .Case("0xaf", "thunderx2t99")
215 .Case("0x0af", "thunderx2t99")
216 .Case("0xa1", "thunderxt88")
217 .Case("0x0a1", "thunderxt88")
218 .Default("generic");
219 }
220 }
221 }
222
KAWASHIMA Takahiroc8cd1a92020-03-03 21:52:27 +0900223 if (Implementer == "0x46") { // Fujitsu Ltd.
224 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
225 if (Lines[I].startswith("CPU part")) {
226 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
227 .Case("0x001", "a64fx")
228 .Default("generic");
229 }
230 }
231 }
232
Bryan Chan12355392018-11-09 19:32:08 +0000233 if (Implementer == "0x48") // HiSilicon Technologies, Inc.
234 // Look for the CPU part line.
235 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
236 if (Lines[I].startswith("CPU part"))
237 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
238 // values correspond to the "Part number" in the CP15/c0 register. The
239 // contents are specified in the various processor manuals.
240 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
241 .Case("0xd01", "tsv110")
242 .Default("generic");
243
Simon Pilgrima271c542017-05-03 15:42:29 +0000244 if (Implementer == "0x51") // Qualcomm Technologies, Inc.
245 // Look for the CPU part line.
246 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
247 if (Lines[I].startswith("CPU part"))
248 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
249 // values correspond to the "Part number" in the CP15/c0 register. The
250 // contents are specified in the various processor manuals.
251 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
252 .Case("0x06f", "krait") // APQ8064
253 .Case("0x201", "kryo")
254 .Case("0x205", "kryo")
Eli Friedmanbde9fc72017-09-13 21:48:00 +0000255 .Case("0x211", "kryo")
256 .Case("0x800", "cortex-a73")
257 .Case("0x801", "cortex-a73")
Yi Kong432f48f2019-06-11 00:05:36 +0000258 .Case("0x802", "cortex-a73")
259 .Case("0x803", "cortex-a73")
260 .Case("0x804", "cortex-a73")
261 .Case("0x805", "cortex-a73")
Balaram Makama1e7ecc72017-09-22 17:46:36 +0000262 .Case("0xc00", "falkor")
Chad Rosier71070852017-09-25 14:05:00 +0000263 .Case("0xc01", "saphira")
Simon Pilgrima271c542017-05-03 15:42:29 +0000264 .Default("generic");
265
Evandro Menezes5d7a9e62017-12-08 21:09:59 +0000266 if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
267 // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
268 // any predictive pattern across variants and parts.
269 unsigned Variant = 0, Part = 0;
270
271 // Look for the CPU variant line, whose value is a 1 digit hexadecimal
272 // number, corresponding to the Variant bits in the CP15/C0 register.
273 for (auto I : Lines)
274 if (I.consume_front("CPU variant"))
275 I.ltrim("\t :").getAsInteger(0, Variant);
276
277 // Look for the CPU part line, whose value is a 3 digit hexadecimal
278 // number, corresponding to the PartNum bits in the CP15/C0 register.
279 for (auto I : Lines)
280 if (I.consume_front("CPU part"))
281 I.ltrim("\t :").getAsInteger(0, Part);
282
283 unsigned Exynos = (Variant << 12) | Part;
284 switch (Exynos) {
285 default:
Evandro Menezes215da662019-10-02 16:26:40 -0500286 // Default by falling through to Exynos M3.
Evandro Menezes5d7a9e62017-12-08 21:09:59 +0000287 LLVM_FALLTHROUGH;
Evandro Menezes215da662019-10-02 16:26:40 -0500288 case 0x1002:
289 return "exynos-m3";
290 case 0x1003:
291 return "exynos-m4";
Evandro Menezes5d7a9e62017-12-08 21:09:59 +0000292 }
293 }
294
Simon Pilgrima271c542017-05-03 15:42:29 +0000295 return "generic";
296}
297
Craig Topper8665f592018-03-07 17:53:16 +0000298StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000299 // STIDP is a privileged operation, so use /proc/cpuinfo instead.
300
301 // The "processor 0:" line comes after a fair amount of other information,
302 // including a cache breakdown, but this should be plenty.
303 SmallVector<StringRef, 32> Lines;
304 ProcCpuinfoContent.split(Lines, "\n");
305
306 // Look for the CPU features.
307 SmallVector<StringRef, 32> CPUFeatures;
308 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
309 if (Lines[I].startswith("features")) {
310 size_t Pos = Lines[I].find(":");
311 if (Pos != StringRef::npos) {
312 Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
313 break;
314 }
315 }
316
317 // We need to check for the presence of vector support independently of
318 // the machine type, since we may only use the vector register set when
319 // supported by the kernel (and hypervisor).
320 bool HaveVectorSupport = false;
321 for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
322 if (CPUFeatures[I] == "vx")
323 HaveVectorSupport = true;
324 }
325
326 // Now check the processor machine type.
327 for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
328 if (Lines[I].startswith("processor ")) {
329 size_t Pos = Lines[I].find("machine = ");
330 if (Pos != StringRef::npos) {
331 Pos += sizeof("machine = ") - 1;
332 unsigned int Id;
333 if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
Ulrich Weigand0f0a8b72019-07-12 18:13:16 +0000334 if (Id >= 8561 && HaveVectorSupport)
Ulrich Weigand819c1652019-09-20 23:04:45 +0000335 return "z15";
Ulrich Weigand2b3482f2017-07-17 17:41:11 +0000336 if (Id >= 3906 && HaveVectorSupport)
337 return "z14";
Simon Pilgrima271c542017-05-03 15:42:29 +0000338 if (Id >= 2964 && HaveVectorSupport)
339 return "z13";
340 if (Id >= 2827)
341 return "zEC12";
342 if (Id >= 2817)
343 return "z196";
344 }
345 }
346 break;
347 }
348 }
349
350 return "generic";
351}
352
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000353StringRef sys::detail::getHostCPUNameForBPF() {
354#if !defined(__linux__) || !defined(__x86_64__)
355 return "generic";
356#else
Jiong Wang66b18e52019-02-07 10:43:09 +0000357 uint8_t v3_insns[40] __attribute__ ((aligned (8))) =
358 /* BPF_MOV64_IMM(BPF_REG_0, 0) */
359 { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
360 /* BPF_MOV64_IMM(BPF_REG_2, 1) */
361 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
362 /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
363 0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
364 /* BPF_MOV64_IMM(BPF_REG_0, 1) */
365 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
366 /* BPF_EXIT_INSN() */
367 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
368
369 uint8_t v2_insns[40] __attribute__ ((aligned (8))) =
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000370 /* BPF_MOV64_IMM(BPF_REG_0, 0) */
371 { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
372 /* BPF_MOV64_IMM(BPF_REG_2, 1) */
373 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
374 /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
375 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
376 /* BPF_MOV64_IMM(BPF_REG_0, 1) */
377 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
378 /* BPF_EXIT_INSN() */
379 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
380
381 struct bpf_prog_load_attr {
382 uint32_t prog_type;
383 uint32_t insn_cnt;
384 uint64_t insns;
385 uint64_t license;
386 uint32_t log_level;
387 uint32_t log_size;
388 uint64_t log_buf;
389 uint32_t kern_version;
390 uint32_t prog_flags;
391 } attr = {};
392 attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
393 attr.insn_cnt = 5;
Jiong Wang66b18e52019-02-07 10:43:09 +0000394 attr.insns = (uint64_t)v3_insns;
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000395 attr.license = (uint64_t)"DUMMY";
396
Jiong Wang66b18e52019-02-07 10:43:09 +0000397 int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,
398 sizeof(attr));
399 if (fd >= 0) {
400 close(fd);
401 return "v3";
402 }
403
404 /* Clear the whole attr in case its content changed by syscall. */
405 memset(&attr, 0, sizeof(attr));
406 attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
407 attr.insn_cnt = 5;
408 attr.insns = (uint64_t)v2_insns;
409 attr.license = (uint64_t)"DUMMY";
410 fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
Yonghong Songc6d25712017-08-23 16:24:31 +0000411 if (fd >= 0) {
412 close(fd);
413 return "v2";
414 }
415 return "v1";
Yonghong Songdc1dbf62017-08-23 04:25:57 +0000416#endif
417}
418
Simon Pilgrima271c542017-05-03 15:42:29 +0000419#if defined(__i386__) || defined(_M_IX86) || \
420 defined(__x86_64__) || defined(_M_X64)
421
422enum VendorSignatures {
423 SIG_INTEL = 0x756e6547 /* Genu */,
424 SIG_AMD = 0x68747541 /* Auth */
425};
426
Simon Pilgrima271c542017-05-03 15:42:29 +0000427// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
428// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
429// support. Consequently, for i386, the presence of CPUID is checked first
430// via the corresponding eflags bit.
431// Removal of cpuid.h header motivated by PR30384
432// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
433// or test-suite, but are used in external projects e.g. libstdcxx
434static bool isCpuIdSupported() {
435#if defined(__GNUC__) || defined(__clang__)
436#if defined(__i386__)
437 int __cpuid_supported;
438 __asm__(" pushfl\n"
439 " popl %%eax\n"
440 " movl %%eax,%%ecx\n"
441 " xorl $0x00200000,%%eax\n"
442 " pushl %%eax\n"
443 " popfl\n"
444 " pushfl\n"
445 " popl %%eax\n"
446 " movl $0,%0\n"
447 " cmpl %%eax,%%ecx\n"
448 " je 1f\n"
449 " movl $1,%0\n"
450 "1:"
451 : "=r"(__cpuid_supported)
452 :
453 : "eax", "ecx");
454 if (!__cpuid_supported)
455 return false;
456#endif
457 return true;
458#endif
459 return true;
460}
461
462/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
463/// the specified arguments. If we can't run cpuid on the host, return true.
464static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
465 unsigned *rECX, unsigned *rEDX) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000466#if defined(__GNUC__) || defined(__clang__)
467#if defined(__x86_64__)
468 // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
469 // FIXME: should we save this for Clang?
470 __asm__("movq\t%%rbx, %%rsi\n\t"
471 "cpuid\n\t"
472 "xchgq\t%%rbx, %%rsi\n\t"
473 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
474 : "a"(value));
Craig Topper1efd10a2017-07-10 06:04:11 +0000475 return false;
Simon Pilgrima271c542017-05-03 15:42:29 +0000476#elif defined(__i386__)
477 __asm__("movl\t%%ebx, %%esi\n\t"
478 "cpuid\n\t"
479 "xchgl\t%%ebx, %%esi\n\t"
480 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
481 : "a"(value));
Craig Topper1efd10a2017-07-10 06:04:11 +0000482 return false;
Simon Pilgrima271c542017-05-03 15:42:29 +0000483#else
Craig Topper1efd10a2017-07-10 06:04:11 +0000484 return true;
Simon Pilgrima271c542017-05-03 15:42:29 +0000485#endif
486#elif defined(_MSC_VER)
487 // The MSVC intrinsic is portable across x86 and x64.
488 int registers[4];
489 __cpuid(registers, value);
490 *rEAX = registers[0];
491 *rEBX = registers[1];
492 *rECX = registers[2];
493 *rEDX = registers[3];
Simon Pilgrima271c542017-05-03 15:42:29 +0000494 return false;
495#else
496 return true;
497#endif
498}
499
500/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
501/// the 4 values in the specified arguments. If we can't run cpuid on the host,
502/// return true.
503static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
504 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
505 unsigned *rEDX) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000506#if defined(__GNUC__) || defined(__clang__)
Craig Topper828cf302017-07-17 05:16:16 +0000507#if defined(__x86_64__)
Craig Topperada983a2017-07-10 06:09:22 +0000508 // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
Simon Pilgrima271c542017-05-03 15:42:29 +0000509 // FIXME: should we save this for Clang?
510 __asm__("movq\t%%rbx, %%rsi\n\t"
511 "cpuid\n\t"
512 "xchgq\t%%rbx, %%rsi\n\t"
513 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
514 : "a"(value), "c"(subleaf));
Craig Topper1efd10a2017-07-10 06:04:11 +0000515 return false;
Craig Topper828cf302017-07-17 05:16:16 +0000516#elif defined(__i386__)
517 __asm__("movl\t%%ebx, %%esi\n\t"
518 "cpuid\n\t"
519 "xchgl\t%%ebx, %%esi\n\t"
520 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
521 : "a"(value), "c"(subleaf));
522 return false;
523#else
524 return true;
525#endif
Simon Pilgrima271c542017-05-03 15:42:29 +0000526#elif defined(_MSC_VER)
527 int registers[4];
528 __cpuidex(registers, value, subleaf);
529 *rEAX = registers[0];
530 *rEBX = registers[1];
531 *rECX = registers[2];
532 *rEDX = registers[3];
Craig Topper1efd10a2017-07-10 06:04:11 +0000533 return false;
534#else
535 return true;
Simon Pilgrima271c542017-05-03 15:42:29 +0000536#endif
Simon Pilgrima271c542017-05-03 15:42:29 +0000537}
538
Craig Topperf3af64e2017-07-12 06:49:57 +0000539// Read control register 0 (XCR0). Used to detect features such as AVX.
Simon Pilgrima271c542017-05-03 15:42:29 +0000540static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
541#if defined(__GNUC__) || defined(__clang__)
542 // Check xgetbv; this uses a .byte sequence instead of the instruction
543 // directly because older assemblers do not include support for xgetbv and
544 // there is no easy way to conditionally compile based on the assembler used.
545 __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
546 return false;
547#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
548 unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
549 *rEAX = Result;
550 *rEDX = Result >> 32;
551 return false;
552#else
553 return true;
554#endif
555}
556
557static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
558 unsigned *Model) {
559 *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
560 *Model = (EAX >> 4) & 0xf; // Bits 4 - 7
561 if (*Family == 6 || *Family == 0xf) {
562 if (*Family == 0xf)
563 // Examine extended family ID if family ID is F.
564 *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
565 // Examine extended model ID if family ID is 6 or F.
566 *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
567 }
568}
569
570static void
Craig Topperc6bbe4b2017-07-08 05:16:14 +0000571getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
572 unsigned Brand_id, unsigned Features,
Craig Topper0aca35d2018-10-20 03:51:43 +0000573 unsigned Features2, unsigned Features3,
574 unsigned *Type, unsigned *Subtype) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000575 if (Brand_id != 0)
576 return;
577 switch (Family) {
578 case 3:
Craig Topperc77d00e2017-11-10 17:10:57 +0000579 *Type = X86::INTEL_i386;
Simon Pilgrima271c542017-05-03 15:42:29 +0000580 break;
581 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000582 *Type = X86::INTEL_i486;
Simon Pilgrima271c542017-05-03 15:42:29 +0000583 break;
584 case 5:
Craig Topper47c87392017-11-21 23:36:42 +0000585 if (Features & (1 << X86::FEATURE_MMX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000586 *Type = X86::INTEL_PENTIUM_MMX;
Simon Pilgrima271c542017-05-03 15:42:29 +0000587 break;
588 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000589 *Type = X86::INTEL_PENTIUM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000590 break;
591 case 6:
592 switch (Model) {
593 case 0x01: // Pentium Pro processor
Craig Topperc77d00e2017-11-10 17:10:57 +0000594 *Type = X86::INTEL_PENTIUM_PRO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000595 break;
596 case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
597 // model 03
598 case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
599 // model 05, and Intel Celeron processor, model 05
600 case 0x06: // Celeron processor, model 06
Craig Topperc77d00e2017-11-10 17:10:57 +0000601 *Type = X86::INTEL_PENTIUM_II;
Simon Pilgrima271c542017-05-03 15:42:29 +0000602 break;
603 case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
604 // processor, model 07
605 case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
606 // model 08, and Celeron processor, model 08
607 case 0x0a: // Pentium III Xeon processor, model 0Ah
608 case 0x0b: // Pentium III processor, model 0Bh
Craig Topperc77d00e2017-11-10 17:10:57 +0000609 *Type = X86::INTEL_PENTIUM_III;
Simon Pilgrima271c542017-05-03 15:42:29 +0000610 break;
611 case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
612 case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
613 // 0Dh. All processors are manufactured using the 90 nm process.
614 case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
615 // Integrated Processor with Intel QuickAssist Technology
Craig Topperc77d00e2017-11-10 17:10:57 +0000616 *Type = X86::INTEL_PENTIUM_M;
Simon Pilgrima271c542017-05-03 15:42:29 +0000617 break;
618 case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
619 // 0Eh. All processors are manufactured using the 65 nm process.
Craig Topperc77d00e2017-11-10 17:10:57 +0000620 *Type = X86::INTEL_CORE_DUO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000621 break; // yonah
622 case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
623 // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
624 // mobile processor, Intel Core 2 Extreme processor, Intel
625 // Pentium Dual-Core processor, Intel Xeon processor, model
626 // 0Fh. All processors are manufactured using the 65 nm process.
627 case 0x16: // Intel Celeron processor model 16h. All processors are
628 // manufactured using the 65 nm process
Craig Topperc77d00e2017-11-10 17:10:57 +0000629 *Type = X86::INTEL_CORE2; // "core2"
630 *Subtype = X86::INTEL_CORE2_65;
Simon Pilgrima271c542017-05-03 15:42:29 +0000631 break;
632 case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
633 // 17h. All processors are manufactured using the 45 nm process.
634 //
635 // 45nm: Penryn , Wolfdale, Yorkfield (XE)
636 case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
637 // the 45 nm process.
Craig Topperc77d00e2017-11-10 17:10:57 +0000638 *Type = X86::INTEL_CORE2; // "penryn"
639 *Subtype = X86::INTEL_CORE2_45;
Simon Pilgrima271c542017-05-03 15:42:29 +0000640 break;
641 case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
642 // processors are manufactured using the 45 nm process.
643 case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
644 // As found in a Summer 2010 model iMac.
645 case 0x1f:
646 case 0x2e: // Nehalem EX
Craig Topperc77d00e2017-11-10 17:10:57 +0000647 *Type = X86::INTEL_COREI7; // "nehalem"
648 *Subtype = X86::INTEL_COREI7_NEHALEM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000649 break;
650 case 0x25: // Intel Core i7, laptop version.
651 case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
652 // processors are manufactured using the 32 nm process.
653 case 0x2f: // Westmere EX
Craig Topperc77d00e2017-11-10 17:10:57 +0000654 *Type = X86::INTEL_COREI7; // "westmere"
655 *Subtype = X86::INTEL_COREI7_WESTMERE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000656 break;
657 case 0x2a: // Intel Core i7 processor. All processors are manufactured
658 // using the 32 nm process.
659 case 0x2d:
Craig Topperc77d00e2017-11-10 17:10:57 +0000660 *Type = X86::INTEL_COREI7; //"sandybridge"
661 *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000662 break;
663 case 0x3a:
664 case 0x3e: // Ivy Bridge EP
Craig Topperc77d00e2017-11-10 17:10:57 +0000665 *Type = X86::INTEL_COREI7; // "ivybridge"
666 *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000667 break;
668
669 // Haswell:
670 case 0x3c:
671 case 0x3f:
672 case 0x45:
673 case 0x46:
Craig Topperc77d00e2017-11-10 17:10:57 +0000674 *Type = X86::INTEL_COREI7; // "haswell"
675 *Subtype = X86::INTEL_COREI7_HASWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000676 break;
677
678 // Broadwell:
679 case 0x3d:
680 case 0x47:
681 case 0x4f:
682 case 0x56:
Craig Topperc77d00e2017-11-10 17:10:57 +0000683 *Type = X86::INTEL_COREI7; // "broadwell"
684 *Subtype = X86::INTEL_COREI7_BROADWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000685 break;
686
687 // Skylake:
Craig Topperc6696292019-05-31 19:18:07 +0000688 case 0x4e: // Skylake mobile
689 case 0x5e: // Skylake desktop
690 case 0x8e: // Kaby Lake mobile
691 case 0x9e: // Kaby Lake desktop
Craig Topperc77d00e2017-11-10 17:10:57 +0000692 *Type = X86::INTEL_COREI7; // "skylake"
693 *Subtype = X86::INTEL_COREI7_SKYLAKE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000694 break;
695
696 // Skylake Xeon:
697 case 0x55:
Craig Topperc77d00e2017-11-10 17:10:57 +0000698 *Type = X86::INTEL_COREI7;
Craig Topper54658752019-09-04 16:01:43 +0000699 if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32)))
Pengfei Wangf8b28932019-06-07 08:31:35 +0000700 *Subtype = X86::INTEL_COREI7_COOPERLAKE; // "cooperlake"
701 else if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32)))
Craig Topperc6696292019-05-31 19:18:07 +0000702 *Subtype = X86::INTEL_COREI7_CASCADELAKE; // "cascadelake"
703 else
704 *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512"
Simon Pilgrima271c542017-05-03 15:42:29 +0000705 break;
706
Craig Topper07491862017-11-15 06:02:42 +0000707 // Cannonlake:
708 case 0x66:
709 *Type = X86::INTEL_COREI7;
710 *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake"
711 break;
712
Craig Toppercac6b762019-05-20 16:58:23 +0000713 // Icelake:
Craig Topper2f1895e2019-05-22 19:51:35 +0000714 case 0x7d:
Craig Toppercac6b762019-05-20 16:58:23 +0000715 case 0x7e:
716 *Type = X86::INTEL_COREI7;
717 *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; // "icelake-client"
718 break;
719
Craig Topper2f1895e2019-05-22 19:51:35 +0000720 // Icelake Xeon:
721 case 0x6a:
722 case 0x6c:
723 *Type = X86::INTEL_COREI7;
724 *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER; // "icelake-server"
725 break;
726
Simon Pilgrima271c542017-05-03 15:42:29 +0000727 case 0x1c: // Most 45 nm Intel Atom processors
728 case 0x26: // 45 nm Atom Lincroft
729 case 0x27: // 32 nm Atom Medfield
730 case 0x35: // 32 nm Atom Midview
731 case 0x36: // 32 nm Atom Midview
Craig Topperc77d00e2017-11-10 17:10:57 +0000732 *Type = X86::INTEL_BONNELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000733 break; // "bonnell"
734
735 // Atom Silvermont codes from the Intel software optimization guide.
736 case 0x37:
737 case 0x4a:
738 case 0x4d:
739 case 0x5a:
740 case 0x5d:
741 case 0x4c: // really airmont
Craig Topperc77d00e2017-11-10 17:10:57 +0000742 *Type = X86::INTEL_SILVERMONT;
Simon Pilgrima271c542017-05-03 15:42:29 +0000743 break; // "silvermont"
Michael Zuckerman4bcb9c32017-06-29 10:00:33 +0000744 // Goldmont:
Craig Topper0dadfe32017-11-15 06:02:43 +0000745 case 0x5c: // Apollo Lake
746 case 0x5f: // Denverton
Craig Topperc77d00e2017-11-10 17:10:57 +0000747 *Type = X86::INTEL_GOLDMONT;
Michael Zuckerman4bcb9c32017-06-29 10:00:33 +0000748 break; // "goldmont"
Gabor Buella8f1646b2018-04-16 07:47:35 +0000749 case 0x7a:
750 *Type = X86::INTEL_GOLDMONT_PLUS;
751 break;
Craig Toppercac6b762019-05-20 16:58:23 +0000752 case 0x86:
753 *Type = X86::INTEL_TREMONT;
754 break;
Craig Topperc6696292019-05-31 19:18:07 +0000755
Simon Pilgrima271c542017-05-03 15:42:29 +0000756 case 0x57:
Craig Topperc77d00e2017-11-10 17:10:57 +0000757 *Type = X86::INTEL_KNL; // knl
Simon Pilgrima271c542017-05-03 15:42:29 +0000758 break;
Craig Topperc6696292019-05-31 19:18:07 +0000759
Craig Topper5d692912017-10-13 18:10:17 +0000760 case 0x85:
Craig Topperc77d00e2017-11-10 17:10:57 +0000761 *Type = X86::INTEL_KNM; // knm
Craig Topper5d692912017-10-13 18:10:17 +0000762 break;
Simon Pilgrima271c542017-05-03 15:42:29 +0000763
764 default: // Unknown family 6 CPU, try to guess.
Pengfei Wange28cbbd2019-08-12 01:29:46 +0000765 // TODO detect tigerlake host
766 if (Features3 & (1 << (X86::FEATURE_AVX512VP2INTERSECT - 64))) {
767 *Type = X86::INTEL_COREI7;
768 *Subtype = X86::INTEL_COREI7_TIGERLAKE;
769 break;
770 }
771
Craig Topperaa3f2492018-11-15 18:11:52 +0000772 if (Features & (1 << X86::FEATURE_AVX512VBMI2)) {
773 *Type = X86::INTEL_COREI7;
774 *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
775 break;
776 }
777
Craig Topper47c87392017-11-21 23:36:42 +0000778 if (Features & (1 << X86::FEATURE_AVX512VBMI)) {
Craig Topper07491862017-11-15 06:02:42 +0000779 *Type = X86::INTEL_COREI7;
780 *Subtype = X86::INTEL_COREI7_CANNONLAKE;
Craig Topper4eda7562017-07-27 03:26:52 +0000781 break;
782 }
Craig Topper07491862017-11-15 06:02:42 +0000783
Craig Topper54658752019-09-04 16:01:43 +0000784 if (Features2 & (1 << (X86::FEATURE_AVX512BF16 - 32))) {
Pengfei Wangf8b28932019-06-07 08:31:35 +0000785 *Type = X86::INTEL_COREI7;
786 *Subtype = X86::INTEL_COREI7_COOPERLAKE;
787 break;
788 }
789
Craig Topper5fb34b52018-11-27 18:05:00 +0000790 if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32))) {
791 *Type = X86::INTEL_COREI7;
792 *Subtype = X86::INTEL_COREI7_CASCADELAKE;
793 break;
794 }
795
Craig Topper47c87392017-11-21 23:36:42 +0000796 if (Features & (1 << X86::FEATURE_AVX512VL)) {
Craig Topper07491862017-11-15 06:02:42 +0000797 *Type = X86::INTEL_COREI7;
798 *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
799 break;
800 }
801
Craig Topper47c87392017-11-21 23:36:42 +0000802 if (Features & (1 << X86::FEATURE_AVX512ER)) {
Craig Topper07491862017-11-15 06:02:42 +0000803 *Type = X86::INTEL_KNL; // knl
804 break;
805 }
806
Craig Topper0aca35d2018-10-20 03:51:43 +0000807 if (Features3 & (1 << (X86::FEATURE_CLFLUSHOPT - 64))) {
808 if (Features3 & (1 << (X86::FEATURE_SHA - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000809 *Type = X86::INTEL_GOLDMONT;
Craig Topper4eda7562017-07-27 03:26:52 +0000810 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000811 *Type = X86::INTEL_COREI7;
812 *Subtype = X86::INTEL_COREI7_SKYLAKE;
Craig Topper4eda7562017-07-27 03:26:52 +0000813 }
Simon Pilgrima271c542017-05-03 15:42:29 +0000814 break;
815 }
Craig Topper0aca35d2018-10-20 03:51:43 +0000816 if (Features3 & (1 << (X86::FEATURE_ADX - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000817 *Type = X86::INTEL_COREI7;
818 *Subtype = X86::INTEL_COREI7_BROADWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000819 break;
820 }
Craig Topper47c87392017-11-21 23:36:42 +0000821 if (Features & (1 << X86::FEATURE_AVX2)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000822 *Type = X86::INTEL_COREI7;
823 *Subtype = X86::INTEL_COREI7_HASWELL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000824 break;
825 }
Craig Topper47c87392017-11-21 23:36:42 +0000826 if (Features & (1 << X86::FEATURE_AVX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000827 *Type = X86::INTEL_COREI7;
828 *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000829 break;
830 }
Craig Topper47c87392017-11-21 23:36:42 +0000831 if (Features & (1 << X86::FEATURE_SSE4_2)) {
Craig Topper0aca35d2018-10-20 03:51:43 +0000832 if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000833 *Type = X86::INTEL_SILVERMONT;
Simon Pilgrima271c542017-05-03 15:42:29 +0000834 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000835 *Type = X86::INTEL_COREI7;
836 *Subtype = X86::INTEL_COREI7_NEHALEM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000837 }
838 break;
839 }
Craig Topper47c87392017-11-21 23:36:42 +0000840 if (Features & (1 << X86::FEATURE_SSE4_1)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000841 *Type = X86::INTEL_CORE2; // "penryn"
842 *Subtype = X86::INTEL_CORE2_45;
Simon Pilgrima271c542017-05-03 15:42:29 +0000843 break;
844 }
Craig Topper47c87392017-11-21 23:36:42 +0000845 if (Features & (1 << X86::FEATURE_SSSE3)) {
Craig Topper0aca35d2018-10-20 03:51:43 +0000846 if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000847 *Type = X86::INTEL_BONNELL; // "bonnell"
Simon Pilgrima271c542017-05-03 15:42:29 +0000848 } else {
Craig Topperc77d00e2017-11-10 17:10:57 +0000849 *Type = X86::INTEL_CORE2; // "core2"
850 *Subtype = X86::INTEL_CORE2_65;
Simon Pilgrima271c542017-05-03 15:42:29 +0000851 }
852 break;
853 }
Craig Topper0aca35d2018-10-20 03:51:43 +0000854 if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000855 *Type = X86::INTEL_CORE2; // "core2"
856 *Subtype = X86::INTEL_CORE2_65;
Craig Toppera233e162017-11-02 19:13:32 +0000857 break;
858 }
Craig Topper47c87392017-11-21 23:36:42 +0000859 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000860 *Type = X86::INTEL_CORE_DUO;
Craig Toppera233e162017-11-02 19:13:32 +0000861 break;
Simon Pilgrima271c542017-05-03 15:42:29 +0000862 }
Craig Topper47c87392017-11-21 23:36:42 +0000863 if (Features & (1 << X86::FEATURE_SSE2)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000864 *Type = X86::INTEL_PENTIUM_M;
Simon Pilgrima271c542017-05-03 15:42:29 +0000865 break;
866 }
Craig Topper47c87392017-11-21 23:36:42 +0000867 if (Features & (1 << X86::FEATURE_SSE)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000868 *Type = X86::INTEL_PENTIUM_III;
Simon Pilgrima271c542017-05-03 15:42:29 +0000869 break;
870 }
Craig Topper47c87392017-11-21 23:36:42 +0000871 if (Features & (1 << X86::FEATURE_MMX)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000872 *Type = X86::INTEL_PENTIUM_II;
Simon Pilgrima271c542017-05-03 15:42:29 +0000873 break;
874 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000875 *Type = X86::INTEL_PENTIUM_PRO;
Simon Pilgrima271c542017-05-03 15:42:29 +0000876 break;
877 }
878 break;
879 case 15: {
Craig Topper0aca35d2018-10-20 03:51:43 +0000880 if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000881 *Type = X86::INTEL_NOCONA;
Simon Pilgrima271c542017-05-03 15:42:29 +0000882 break;
883 }
Craig Topper47c87392017-11-21 23:36:42 +0000884 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000885 *Type = X86::INTEL_PRESCOTT;
Craig Topper14949152017-11-02 19:13:34 +0000886 break;
887 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000888 *Type = X86::INTEL_PENTIUM_IV;
Simon Pilgrima271c542017-05-03 15:42:29 +0000889 break;
890 }
891 default:
892 break; /*"generic"*/
893 }
894}
895
Craig Topper2ace1532017-07-08 06:44:34 +0000896static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
897 unsigned Features, unsigned *Type,
Simon Pilgrima271c542017-05-03 15:42:29 +0000898 unsigned *Subtype) {
899 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
900 // appears to be no way to generate the wide variety of AMD-specific targets
901 // from the information returned from CPUID.
902 switch (Family) {
903 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000904 *Type = X86::AMD_i486;
Simon Pilgrima271c542017-05-03 15:42:29 +0000905 break;
906 case 5:
Craig Topperc77d00e2017-11-10 17:10:57 +0000907 *Type = X86::AMDPENTIUM;
Simon Pilgrima271c542017-05-03 15:42:29 +0000908 switch (Model) {
909 case 6:
910 case 7:
Craig Topperc77d00e2017-11-10 17:10:57 +0000911 *Subtype = X86::AMDPENTIUM_K6;
Simon Pilgrima271c542017-05-03 15:42:29 +0000912 break; // "k6"
913 case 8:
Craig Topperc77d00e2017-11-10 17:10:57 +0000914 *Subtype = X86::AMDPENTIUM_K62;
Simon Pilgrima271c542017-05-03 15:42:29 +0000915 break; // "k6-2"
916 case 9:
917 case 13:
Craig Topperc77d00e2017-11-10 17:10:57 +0000918 *Subtype = X86::AMDPENTIUM_K63;
Simon Pilgrima271c542017-05-03 15:42:29 +0000919 break; // "k6-3"
920 case 10:
Craig Topperc77d00e2017-11-10 17:10:57 +0000921 *Subtype = X86::AMDPENTIUM_GEODE;
Simon Pilgrima271c542017-05-03 15:42:29 +0000922 break; // "geode"
923 }
924 break;
925 case 6:
Craig Topper47c87392017-11-21 23:36:42 +0000926 if (Features & (1 << X86::FEATURE_SSE)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000927 *Type = X86::AMD_ATHLON_XP;
Simon Pilgrima271c542017-05-03 15:42:29 +0000928 break; // "athlon-xp"
929 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000930 *Type = X86::AMD_ATHLON;
Craig Topperf3de5eb2017-07-13 06:34:10 +0000931 break; // "athlon"
Simon Pilgrima271c542017-05-03 15:42:29 +0000932 case 15:
Craig Topper47c87392017-11-21 23:36:42 +0000933 if (Features & (1 << X86::FEATURE_SSE3)) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000934 *Type = X86::AMD_K8SSE3;
Simon Pilgrima271c542017-05-03 15:42:29 +0000935 break; // "k8-sse3"
936 }
Craig Topperc77d00e2017-11-10 17:10:57 +0000937 *Type = X86::AMD_K8;
Craig Topperf3de5eb2017-07-13 06:34:10 +0000938 break; // "k8"
Simon Pilgrima271c542017-05-03 15:42:29 +0000939 case 16:
Craig Topperc77d00e2017-11-10 17:10:57 +0000940 *Type = X86::AMDFAM10H; // "amdfam10"
Simon Pilgrima271c542017-05-03 15:42:29 +0000941 switch (Model) {
942 case 2:
Craig Topperc77d00e2017-11-10 17:10:57 +0000943 *Subtype = X86::AMDFAM10H_BARCELONA;
Simon Pilgrima271c542017-05-03 15:42:29 +0000944 break;
945 case 4:
Craig Topperc77d00e2017-11-10 17:10:57 +0000946 *Subtype = X86::AMDFAM10H_SHANGHAI;
Simon Pilgrima271c542017-05-03 15:42:29 +0000947 break;
948 case 8:
Craig Topperc77d00e2017-11-10 17:10:57 +0000949 *Subtype = X86::AMDFAM10H_ISTANBUL;
Simon Pilgrima271c542017-05-03 15:42:29 +0000950 break;
951 }
952 break;
953 case 20:
Craig Topperc77d00e2017-11-10 17:10:57 +0000954 *Type = X86::AMD_BTVER1;
Simon Pilgrima271c542017-05-03 15:42:29 +0000955 break; // "btver1";
956 case 21:
Craig Topperc77d00e2017-11-10 17:10:57 +0000957 *Type = X86::AMDFAM15H;
Craig Topper1f9d3c02017-07-08 06:44:35 +0000958 if (Model >= 0x60 && Model <= 0x7f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000959 *Subtype = X86::AMDFAM15H_BDVER4;
Craig Topper3db11702017-07-12 06:49:56 +0000960 break; // "bdver4"; 60h-7Fh: Excavator
Simon Pilgrima271c542017-05-03 15:42:29 +0000961 }
962 if (Model >= 0x30 && Model <= 0x3f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000963 *Subtype = X86::AMDFAM15H_BDVER3;
Simon Pilgrima271c542017-05-03 15:42:29 +0000964 break; // "bdver3"; 30h-3Fh: Steamroller
965 }
Roman Lebedevbc1a9242018-05-01 18:39:31 +0000966 if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000967 *Subtype = X86::AMDFAM15H_BDVER2;
Roman Lebedevbc1a9242018-05-01 18:39:31 +0000968 break; // "bdver2"; 02h, 10h-1Fh: Piledriver
Simon Pilgrima271c542017-05-03 15:42:29 +0000969 }
970 if (Model <= 0x0f) {
Craig Topperc77d00e2017-11-10 17:10:57 +0000971 *Subtype = X86::AMDFAM15H_BDVER1;
Simon Pilgrima271c542017-05-03 15:42:29 +0000972 break; // "bdver1"; 00h-0Fh: Bulldozer
973 }
974 break;
975 case 22:
Craig Topperc77d00e2017-11-10 17:10:57 +0000976 *Type = X86::AMD_BTVER2;
Simon Pilgrima271c542017-05-03 15:42:29 +0000977 break; // "btver2"
978 case 23:
Craig Topperc77d00e2017-11-10 17:10:57 +0000979 *Type = X86::AMDFAM17H;
Craig Topperff75bf62019-11-18 11:31:17 -0800980 if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) {
Ganesh Gopalasubramaniane172d7002019-02-26 16:55:10 +0000981 *Subtype = X86::AMDFAM17H_ZNVER2;
Craig Topperff75bf62019-11-18 11:31:17 -0800982 break; // "znver2"; 30h-3fh, 71h: Zen2
Ganesh Gopalasubramaniane172d7002019-02-26 16:55:10 +0000983 }
984 if (Model <= 0x0f) {
985 *Subtype = X86::AMDFAM17H_ZNVER1;
986 break; // "znver1"; 00h-0Fh: Zen1
987 }
Simon Pilgrima271c542017-05-03 15:42:29 +0000988 break;
989 default:
990 break; // "generic"
991 }
992}
993
Craig Topper3a5d0822017-07-12 06:49:58 +0000994static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
Craig Topper0aca35d2018-10-20 03:51:43 +0000995 unsigned *FeaturesOut, unsigned *Features2Out,
996 unsigned *Features3Out) {
Simon Pilgrima271c542017-05-03 15:42:29 +0000997 unsigned Features = 0;
Craig Topper3a5d0822017-07-12 06:49:58 +0000998 unsigned Features2 = 0;
Craig Topper0aca35d2018-10-20 03:51:43 +0000999 unsigned Features3 = 0;
Craig Topperc6bbe4b2017-07-08 05:16:14 +00001000 unsigned EAX, EBX;
Craig Topper3a5d0822017-07-12 06:49:58 +00001001
Simon Pilgrima7d1a7c2018-10-20 13:16:31 +00001002 auto setFeature = [&](unsigned F) {
1003 if (F < 32)
Craig Topper28659f52018-11-24 20:26:11 +00001004 Features |= 1U << (F & 0x1f);
Simon Pilgrima7d1a7c2018-10-20 13:16:31 +00001005 else if (F < 64)
Craig Topper28659f52018-11-24 20:26:11 +00001006 Features2 |= 1U << ((F - 32) & 0x1f);
Simon Pilgrima7d1a7c2018-10-20 13:16:31 +00001007 else if (F < 96)
Craig Topper28659f52018-11-24 20:26:11 +00001008 Features3 |= 1U << ((F - 64) & 0x1f);
Simon Pilgrima7d1a7c2018-10-20 13:16:31 +00001009 else
1010 llvm_unreachable("Unexpected FeatureBit");
1011 };
Craig Topper0aca35d2018-10-20 03:51:43 +00001012
Craig Topper3a5d0822017-07-12 06:49:58 +00001013 if ((EDX >> 15) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001014 setFeature(X86::FEATURE_CMOV);
Craig Topper3a5d0822017-07-12 06:49:58 +00001015 if ((EDX >> 23) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001016 setFeature(X86::FEATURE_MMX);
Craig Topper3a5d0822017-07-12 06:49:58 +00001017 if ((EDX >> 25) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001018 setFeature(X86::FEATURE_SSE);
Craig Topper3a5d0822017-07-12 06:49:58 +00001019 if ((EDX >> 26) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001020 setFeature(X86::FEATURE_SSE2);
Craig Topper3a5d0822017-07-12 06:49:58 +00001021
1022 if ((ECX >> 0) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001023 setFeature(X86::FEATURE_SSE3);
Craig Topper3a5d0822017-07-12 06:49:58 +00001024 if ((ECX >> 1) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001025 setFeature(X86::FEATURE_PCLMUL);
Craig Topper3a5d0822017-07-12 06:49:58 +00001026 if ((ECX >> 9) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001027 setFeature(X86::FEATURE_SSSE3);
Craig Topper3a5d0822017-07-12 06:49:58 +00001028 if ((ECX >> 12) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001029 setFeature(X86::FEATURE_FMA);
Craig Topper3a5d0822017-07-12 06:49:58 +00001030 if ((ECX >> 19) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001031 setFeature(X86::FEATURE_SSE4_1);
Craig Topper3a5d0822017-07-12 06:49:58 +00001032 if ((ECX >> 20) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001033 setFeature(X86::FEATURE_SSE4_2);
Craig Topper3a5d0822017-07-12 06:49:58 +00001034 if ((ECX >> 23) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001035 setFeature(X86::FEATURE_POPCNT);
Craig Topper3a5d0822017-07-12 06:49:58 +00001036 if ((ECX >> 25) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001037 setFeature(X86::FEATURE_AES);
Craig Topper3a5d0822017-07-12 06:49:58 +00001038
1039 if ((ECX >> 22) & 1)
Craig Topper0aca35d2018-10-20 03:51:43 +00001040 setFeature(X86::FEATURE_MOVBE);
Simon Pilgrima271c542017-05-03 15:42:29 +00001041
1042 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1043 // indicates that the AVX registers will be saved and restored on context
1044 // switch, then we have full AVX support.
1045 const unsigned AVXBits = (1 << 27) | (1 << 28);
1046 bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
1047 ((EAX & 0x6) == 0x6);
Florian Hahn82921bf2019-11-21 09:03:16 +00001048#if defined(__APPLE__)
1049 // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1050 // save the AVX512 context if we use AVX512 instructions, even the bit is not
1051 // set right now.
1052 bool HasAVX512Save = true;
1053#else
1054 // AVX512 requires additional context to be saved by the OS.
Simon Pilgrima271c542017-05-03 15:42:29 +00001055 bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
Florian Hahn82921bf2019-11-21 09:03:16 +00001056#endif
Craig Topper3a5d0822017-07-12 06:49:58 +00001057
1058 if (HasAVX)
Craig Topper0aca35d2018-10-20 03:51:43 +00001059 setFeature(X86::FEATURE_AVX);
Craig Topper3a5d0822017-07-12 06:49:58 +00001060
Simon Pilgrima271c542017-05-03 15:42:29 +00001061 bool HasLeaf7 =
1062 MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
Craig Topper3a5d0822017-07-12 06:49:58 +00001063
1064 if (HasLeaf7 && ((EBX >> 3) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001065 setFeature(X86::FEATURE_BMI);
Craig Topper3a5d0822017-07-12 06:49:58 +00001066 if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
Craig Topper0aca35d2018-10-20 03:51:43 +00001067 setFeature(X86::FEATURE_AVX2);
Eric Christopher1d73e222019-08-05 21:25:59 +00001068 if (HasLeaf7 && ((EBX >> 8) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001069 setFeature(X86::FEATURE_BMI2);
Craig Topper3a5d0822017-07-12 06:49:58 +00001070 if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001071 setFeature(X86::FEATURE_AVX512F);
Craig Topper3a5d0822017-07-12 06:49:58 +00001072 if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001073 setFeature(X86::FEATURE_AVX512DQ);
Craig Topper3a5d0822017-07-12 06:49:58 +00001074 if (HasLeaf7 && ((EBX >> 19) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001075 setFeature(X86::FEATURE_ADX);
Craig Topper3a5d0822017-07-12 06:49:58 +00001076 if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001077 setFeature(X86::FEATURE_AVX512IFMA);
Craig Topper4eda7562017-07-27 03:26:52 +00001078 if (HasLeaf7 && ((EBX >> 23) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001079 setFeature(X86::FEATURE_CLFLUSHOPT);
Craig Topper3a5d0822017-07-12 06:49:58 +00001080 if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001081 setFeature(X86::FEATURE_AVX512PF);
Craig Topper3a5d0822017-07-12 06:49:58 +00001082 if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001083 setFeature(X86::FEATURE_AVX512ER);
Craig Topper3a5d0822017-07-12 06:49:58 +00001084 if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001085 setFeature(X86::FEATURE_AVX512CD);
Craig Topper4eda7562017-07-27 03:26:52 +00001086 if (HasLeaf7 && ((EBX >> 29) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001087 setFeature(X86::FEATURE_SHA);
Craig Topper3a5d0822017-07-12 06:49:58 +00001088 if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001089 setFeature(X86::FEATURE_AVX512BW);
Craig Topper3a5d0822017-07-12 06:49:58 +00001090 if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001091 setFeature(X86::FEATURE_AVX512VL);
Craig Topper3a5d0822017-07-12 06:49:58 +00001092
1093 if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001094 setFeature(X86::FEATURE_AVX512VBMI);
1095 if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
1096 setFeature(X86::FEATURE_AVX512VBMI2);
1097 if (HasLeaf7 && ((ECX >> 8) & 1))
1098 setFeature(X86::FEATURE_GFNI);
1099 if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
1100 setFeature(X86::FEATURE_VPCLMULQDQ);
1101 if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
1102 setFeature(X86::FEATURE_AVX512VNNI);
1103 if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
1104 setFeature(X86::FEATURE_AVX512BITALG);
Craig Topper3a5d0822017-07-12 06:49:58 +00001105 if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001106 setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
Craig Topper3a5d0822017-07-12 06:49:58 +00001107
1108 if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001109 setFeature(X86::FEATURE_AVX5124VNNIW);
Craig Topper3a5d0822017-07-12 06:49:58 +00001110 if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
Craig Topper0aca35d2018-10-20 03:51:43 +00001111 setFeature(X86::FEATURE_AVX5124FMAPS);
Pengfei Wange28cbbd2019-08-12 01:29:46 +00001112 if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
1113 setFeature(X86::FEATURE_AVX512VP2INTERSECT);
Simon Pilgrima271c542017-05-03 15:42:29 +00001114
Craig Topper54658752019-09-04 16:01:43 +00001115 bool HasLeaf7Subleaf1 =
1116 MaxLeaf >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1117 if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
1118 setFeature(X86::FEATURE_AVX512BF16);
1119
Craig Topperbb8c7992017-07-08 05:16:13 +00001120 unsigned MaxExtLevel;
1121 getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1122
1123 bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1124 !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
Craig Topper3a5d0822017-07-12 06:49:58 +00001125 if (HasExtLeaf1 && ((ECX >> 6) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001126 setFeature(X86::FEATURE_SSE4_A);
Craig Topper3a5d0822017-07-12 06:49:58 +00001127 if (HasExtLeaf1 && ((ECX >> 11) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001128 setFeature(X86::FEATURE_XOP);
Craig Topper3a5d0822017-07-12 06:49:58 +00001129 if (HasExtLeaf1 && ((ECX >> 16) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001130 setFeature(X86::FEATURE_FMA4);
Craig Topperbb8c7992017-07-08 05:16:13 +00001131
Craig Topper3a5d0822017-07-12 06:49:58 +00001132 if (HasExtLeaf1 && ((EDX >> 29) & 1))
Craig Topper0aca35d2018-10-20 03:51:43 +00001133 setFeature(X86::FEATURE_EM64T);
Craig Topper3a5d0822017-07-12 06:49:58 +00001134
1135 *FeaturesOut = Features;
1136 *Features2Out = Features2;
Craig Topper0aca35d2018-10-20 03:51:43 +00001137 *Features3Out = Features3;
Simon Pilgrima271c542017-05-03 15:42:29 +00001138}
1139
1140StringRef sys::getHostCPUName() {
1141 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1142 unsigned MaxLeaf, Vendor;
1143
1144#if defined(__GNUC__) || defined(__clang__)
1145 //FIXME: include cpuid.h from clang or copy __get_cpuid_max here
1146 // and simplify it to not invoke __cpuid (like cpu_model.c in
1147 // compiler-rt/lib/builtins/cpu_model.c?
1148 // Opting for the second option.
1149 if(!isCpuIdSupported())
1150 return "generic";
1151#endif
Craig Topperbb8c7992017-07-08 05:16:13 +00001152 if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1)
Simon Pilgrima271c542017-05-03 15:42:29 +00001153 return "generic";
Craig Topperbb8c7992017-07-08 05:16:13 +00001154 getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
Simon Pilgrima271c542017-05-03 15:42:29 +00001155
1156 unsigned Brand_id = EBX & 0xff;
1157 unsigned Family = 0, Model = 0;
Craig Topper0aca35d2018-10-20 03:51:43 +00001158 unsigned Features = 0, Features2 = 0, Features3 = 0;
Simon Pilgrima271c542017-05-03 15:42:29 +00001159 detectX86FamilyModel(EAX, &Family, &Model);
Craig Topper0aca35d2018-10-20 03:51:43 +00001160 getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2, &Features3);
Simon Pilgrima271c542017-05-03 15:42:29 +00001161
Craig Topper741e7e62017-11-03 18:02:44 +00001162 unsigned Type = 0;
1163 unsigned Subtype = 0;
Simon Pilgrima271c542017-05-03 15:42:29 +00001164
1165 if (Vendor == SIG_INTEL) {
Craig Topper3a5d0822017-07-12 06:49:58 +00001166 getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features,
Craig Topper0aca35d2018-10-20 03:51:43 +00001167 Features2, Features3, &Type, &Subtype);
Simon Pilgrima271c542017-05-03 15:42:29 +00001168 } else if (Vendor == SIG_AMD) {
1169 getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
Simon Pilgrima271c542017-05-03 15:42:29 +00001170 }
Craig Topperc77d00e2017-11-10 17:10:57 +00001171
1172 // Check subtypes first since those are more specific.
1173#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
1174 if (Subtype == X86::ENUM) \
1175 return ARCHNAME;
1176#include "llvm/Support/X86TargetParser.def"
1177
1178 // Now check types.
Craig Topper55ad3292018-03-06 22:45:31 +00001179#define X86_CPU_TYPE(ARCHNAME, ENUM) \
Craig Topperc77d00e2017-11-10 17:10:57 +00001180 if (Type == X86::ENUM) \
1181 return ARCHNAME;
1182#include "llvm/Support/X86TargetParser.def"
1183
Simon Pilgrima271c542017-05-03 15:42:29 +00001184 return "generic";
1185}
1186
1187#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
1188StringRef sys::getHostCPUName() {
1189 host_basic_info_data_t hostInfo;
1190 mach_msg_type_number_t infoCount;
1191
1192 infoCount = HOST_BASIC_INFO_COUNT;
Kristina Brooks51ae9342018-09-04 10:54:09 +00001193 mach_port_t hostPort = mach_host_self();
1194 host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
Simon Pilgrima271c542017-05-03 15:42:29 +00001195 &infoCount);
Kristina Brooks51ae9342018-09-04 10:54:09 +00001196 mach_port_deallocate(mach_task_self(), hostPort);
Simon Pilgrima271c542017-05-03 15:42:29 +00001197
1198 if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
1199 return "generic";
1200
1201 switch (hostInfo.cpu_subtype) {
1202 case CPU_SUBTYPE_POWERPC_601:
1203 return "601";
1204 case CPU_SUBTYPE_POWERPC_602:
1205 return "602";
1206 case CPU_SUBTYPE_POWERPC_603:
1207 return "603";
1208 case CPU_SUBTYPE_POWERPC_603e:
1209 return "603e";
1210 case CPU_SUBTYPE_POWERPC_603ev:
1211 return "603ev";
1212 case CPU_SUBTYPE_POWERPC_604:
1213 return "604";
1214 case CPU_SUBTYPE_POWERPC_604e:
1215 return "604e";
1216 case CPU_SUBTYPE_POWERPC_620:
1217 return "620";
1218 case CPU_SUBTYPE_POWERPC_750:
1219 return "750";
1220 case CPU_SUBTYPE_POWERPC_7400:
1221 return "7400";
1222 case CPU_SUBTYPE_POWERPC_7450:
1223 return "7450";
1224 case CPU_SUBTYPE_POWERPC_970:
1225 return "970";
1226 default:;
1227 }
1228
1229 return "generic";
1230}
1231#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
1232StringRef sys::getHostCPUName() {
1233 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
Craig Topper8665f592018-03-07 17:53:16 +00001234 StringRef Content = P ? P->getBuffer() : "";
Simon Pilgrima271c542017-05-03 15:42:29 +00001235 return detail::getHostCPUNameForPowerPC(Content);
1236}
1237#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1238StringRef sys::getHostCPUName() {
1239 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
Craig Topper8665f592018-03-07 17:53:16 +00001240 StringRef Content = P ? P->getBuffer() : "";
Simon Pilgrima271c542017-05-03 15:42:29 +00001241 return detail::getHostCPUNameForARM(Content);
1242}
1243#elif defined(__linux__) && defined(__s390x__)
1244StringRef sys::getHostCPUName() {
1245 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
Craig Topper8665f592018-03-07 17:53:16 +00001246 StringRef Content = P ? P->getBuffer() : "";
Simon Pilgrima271c542017-05-03 15:42:29 +00001247 return detail::getHostCPUNameForS390x(Content);
1248}
Chris Bieneman34688fa2019-10-30 12:50:04 -07001249#elif defined(__APPLE__) && defined(__aarch64__)
1250StringRef sys::getHostCPUName() {
1251 return "cyclone";
1252}
1253#elif defined(__APPLE__) && defined(__arm__)
1254StringRef sys::getHostCPUName() {
1255 host_basic_info_data_t hostInfo;
1256 mach_msg_type_number_t infoCount;
1257
1258 infoCount = HOST_BASIC_INFO_COUNT;
1259 mach_port_t hostPort = mach_host_self();
1260 host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
1261 &infoCount);
1262 mach_port_deallocate(mach_task_self(), hostPort);
1263
1264 if (hostInfo.cpu_type != CPU_TYPE_ARM) {
1265 assert(false && "CPUType not equal to ARM should not be possible on ARM");
1266 return "generic";
1267 }
1268 switch (hostInfo.cpu_subtype) {
1269 case CPU_SUBTYPE_ARM_V7S:
1270 return "swift";
1271 default:;
1272 }
Jim Lin466f8842020-02-18 10:48:38 +08001273
Chris Bieneman34688fa2019-10-30 12:50:04 -07001274 return "generic";
1275}
Simon Pilgrima271c542017-05-03 15:42:29 +00001276#else
1277StringRef sys::getHostCPUName() { return "generic"; }
1278#endif
1279
1280#if defined(__linux__) && defined(__x86_64__)
1281// On Linux, the number of physical cores can be computed from /proc/cpuinfo,
1282// using the number of unique physical/core id pairs. The following
1283// implementation reads the /proc/cpuinfo format on an x86_64 system.
Alexandre Ganea8404aeb2020-02-13 22:49:57 -05001284int computeHostNumPhysicalCores() {
Simon Pilgrima271c542017-05-03 15:42:29 +00001285 // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be
1286 // mmapped because it appears to have 0 size.
1287 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
1288 llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
1289 if (std::error_code EC = Text.getError()) {
1290 llvm::errs() << "Can't read "
1291 << "/proc/cpuinfo: " << EC.message() << "\n";
1292 return -1;
1293 }
1294 SmallVector<StringRef, 8> strs;
1295 (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
1296 /*KeepEmpty=*/false);
1297 int CurPhysicalId = -1;
1298 int CurCoreId = -1;
1299 SmallSet<std::pair<int, int>, 32> UniqueItems;
1300 for (auto &Line : strs) {
1301 Line = Line.trim();
1302 if (!Line.startswith("physical id") && !Line.startswith("core id"))
1303 continue;
1304 std::pair<StringRef, StringRef> Data = Line.split(':');
1305 auto Name = Data.first.trim();
1306 auto Val = Data.second.trim();
1307 if (Name == "physical id") {
1308 assert(CurPhysicalId == -1 &&
1309 "Expected a core id before seeing another physical id");
1310 Val.getAsInteger(10, CurPhysicalId);
1311 }
1312 if (Name == "core id") {
1313 assert(CurCoreId == -1 &&
1314 "Expected a physical id before seeing another core id");
1315 Val.getAsInteger(10, CurCoreId);
1316 }
1317 if (CurPhysicalId != -1 && CurCoreId != -1) {
1318 UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
1319 CurPhysicalId = -1;
1320 CurCoreId = -1;
1321 }
1322 }
1323 return UniqueItems.size();
1324}
1325#elif defined(__APPLE__) && defined(__x86_64__)
1326#include <sys/param.h>
1327#include <sys/sysctl.h>
1328
1329// Gets the number of *physical cores* on the machine.
Alexandre Ganea8404aeb2020-02-13 22:49:57 -05001330int computeHostNumPhysicalCores() {
Simon Pilgrima271c542017-05-03 15:42:29 +00001331 uint32_t count;
1332 size_t len = sizeof(count);
1333 sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
1334 if (count < 1) {
1335 int nm[2];
1336 nm[0] = CTL_HW;
1337 nm[1] = HW_AVAILCPU;
1338 sysctl(nm, 2, &count, &len, NULL, 0);
1339 if (count < 1)
1340 return -1;
1341 }
1342 return count;
1343}
Amy Huangcb36bfa2020-02-14 15:31:45 -08001344#elif defined(_WIN32) && LLVM_ENABLE_THREADS != 0
Alexandre Ganea8404aeb2020-02-13 22:49:57 -05001345// Defined in llvm/lib/Support/Windows/Threading.inc
1346int computeHostNumPhysicalCores();
Simon Pilgrima271c542017-05-03 15:42:29 +00001347#else
1348// On other systems, return -1 to indicate unknown.
1349static int computeHostNumPhysicalCores() { return -1; }
1350#endif
1351
1352int sys::getHostNumPhysicalCores() {
1353 static int NumCores = computeHostNumPhysicalCores();
1354 return NumCores;
1355}
1356
1357#if defined(__i386__) || defined(_M_IX86) || \
1358 defined(__x86_64__) || defined(_M_X64)
1359bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1360 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1361 unsigned MaxLevel;
1362 union {
1363 unsigned u[3];
1364 char c[12];
1365 } text;
1366
1367 if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
1368 MaxLevel < 1)
1369 return false;
1370
1371 getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1372
Craig Topper8d464032019-03-20 23:35:49 +00001373 Features["cx8"] = (EDX >> 8) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001374 Features["cmov"] = (EDX >> 15) & 1;
1375 Features["mmx"] = (EDX >> 23) & 1;
Craig Topper6829ca92019-02-13 18:21:36 +00001376 Features["fxsr"] = (EDX >> 24) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001377 Features["sse"] = (EDX >> 25) & 1;
1378 Features["sse2"] = (EDX >> 26) & 1;
1379
1380 Features["sse3"] = (ECX >> 0) & 1;
1381 Features["pclmul"] = (ECX >> 1) & 1;
1382 Features["ssse3"] = (ECX >> 9) & 1;
1383 Features["cx16"] = (ECX >> 13) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001384 Features["sse4.1"] = (ECX >> 19) & 1;
1385 Features["sse4.2"] = (ECX >> 20) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001386 Features["movbe"] = (ECX >> 22) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001387 Features["popcnt"] = (ECX >> 23) & 1;
Craig Topper1af7e442017-11-19 23:30:22 +00001388 Features["aes"] = (ECX >> 25) & 1;
1389 Features["rdrnd"] = (ECX >> 30) & 1;
Simon Pilgrima271c542017-05-03 15:42:29 +00001390
1391 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1392 // indicates that the AVX registers will be saved and restored on context
1393 // switch, then we have full AVX support.
1394 bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
1395 !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
Florian Hahn82921bf2019-11-21 09:03:16 +00001396#if defined(__APPLE__)
1397 // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1398 // save the AVX512 context if we use AVX512 instructions, even the bit is not
1399 // set right now.
1400 bool HasAVX512Save = true;
1401#else
Simon Pilgrima271c542017-05-03 15:42:29 +00001402 // AVX512 requires additional context to be saved by the OS.
1403 bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
Florian Hahn82921bf2019-11-21 09:03:16 +00001404#endif
Simon Pilgrima271c542017-05-03 15:42:29 +00001405
Craig Topper1af7e442017-11-19 23:30:22 +00001406 Features["avx"] = HasAVXSave;
1407 Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;
1408 // Only enable XSAVE if OS has enabled support for saving YMM state.
1409 Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1410 Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave;
1411
Simon Pilgrima271c542017-05-03 15:42:29 +00001412 unsigned MaxExtLevel;
1413 getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1414
1415 bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1416 !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
Craig Topper8d02be32018-02-17 16:52:49 +00001417 Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1);
Craig Topper1af7e442017-11-19 23:30:22 +00001418 Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
1419 Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
1420 Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
1421 Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1422 Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1);
1423 Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1424 Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001425 Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1426
Craig Topper6cdab202018-09-24 18:55:41 +00001427 Features["64bit"] = HasExtLeaf1 && ((EDX >> 29) & 1);
1428
Gabor Buella2ef36f32018-04-11 20:01:57 +00001429 // Miscellaneous memory related features, detected by
1430 // using the 0x80000008 leaf of the CPUID instruction
Simon Pilgrima271c542017-05-03 15:42:29 +00001431 bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
Craig Topperdcd69792017-11-19 23:49:19 +00001432 !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
Gabor Buella2ef36f32018-04-11 20:01:57 +00001433 Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1);
1434 Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001435
1436 bool HasLeaf7 =
1437 MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1438
Craig Topper1af7e442017-11-19 23:30:22 +00001439 Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
1440 Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);
1441 Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001442 // AVX2 is only supported if we have the OS save support from AVX.
Craig Topper1af7e442017-11-19 23:30:22 +00001443 Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave;
1444 Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
Gabor Buellad2f1ab12018-05-25 06:32:05 +00001445 Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);
Craig Topper1af7e442017-11-19 23:30:22 +00001446 Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001447 // AVX512 is only supported if the OS supports the context save for it.
Craig Topper1af7e442017-11-19 23:30:22 +00001448 Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1449 Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1450 Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
1451 Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
Simon Pilgrima271c542017-05-03 15:42:29 +00001452 Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
Craig Topper1af7e442017-11-19 23:30:22 +00001453 Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1454 Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);
1455 Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
1456 Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
1457 Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1458 Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
1459 Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1460 Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
Simon Pilgrima271c542017-05-03 15:42:29 +00001461
Craig Topper1af7e442017-11-19 23:30:22 +00001462 Features["prefetchwt1"] = HasLeaf7 && ((ECX >> 0) & 1);
1463 Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;
Craig Topper9b03f672017-11-21 18:50:41 +00001464 Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
Gabor Buella31fa8022018-04-20 18:42:47 +00001465 Features["waitpkg"] = HasLeaf7 && ((ECX >> 5) & 1);
Coby Tayree71e37cc2017-11-21 09:48:44 +00001466 Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save;
Oren Ben Simhonfa582b02017-11-26 13:02:45 +00001467 Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1);
Coby Tayreed8b17be2017-11-26 09:36:41 +00001468 Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1);
Craig Topper9b03f672017-11-21 18:50:41 +00001469 Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave;
1470 Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1471 Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1472 Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
Yonghong Songdc1dbf62017-08-23 04:25:57 +00001473 Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
Craig Topper84b26b92018-01-18 23:52:31 +00001474 Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1);
Gabor Buella604be442018-04-13 07:35:08 +00001475 Features["cldemote"] = HasLeaf7 && ((ECX >> 25) & 1);
Gabor Buellac8ded042018-05-01 10:01:16 +00001476 Features["movdiri"] = HasLeaf7 && ((ECX >> 27) & 1);
1477 Features["movdir64b"] = HasLeaf7 && ((ECX >> 28) & 1);
Pengfei Wang1f67d942019-05-30 03:59:16 +00001478 Features["enqcmd"] = HasLeaf7 && ((ECX >> 29) & 1);
Craig Topper84b26b92018-01-18 23:52:31 +00001479
WangTianQingd08fadd2020-04-02 16:15:34 +08001480 Features["serialize"] = HasLeaf7 && ((EDX >> 14) & 1);
WangTianQinga3dc9492020-04-09 13:15:42 +08001481 Features["tsxldtrk"] = HasLeaf7 && ((EDX >> 16) & 1);
Gabor Buella2b5e9602018-05-08 06:47:36 +00001482 // There are two CPUID leafs which information associated with the pconfig
1483 // instruction:
1484 // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
1485 // bit of EDX), while the EAX=0x1b leaf returns information on the
1486 // availability of specific pconfig leafs.
1487 // The target feature here only refers to the the first of these two.
1488 // Users might need to check for the availability of specific pconfig
1489 // leaves using cpuid, since that information is ignored while
1490 // detecting features using the "-march=native" flag.
1491 // For more info, see X86 ISA docs.
1492 Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
Luo, Yuankebeec41c2019-05-06 08:22:37 +00001493 bool HasLeaf7Subleaf1 =
1494 MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1495 Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;
Gabor Buella2b5e9602018-05-08 06:47:36 +00001496
Simon Pilgrima271c542017-05-03 15:42:29 +00001497 bool HasLeafD = MaxLevel >= 0xd &&
1498 !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1499
1500 // Only enable XSAVE if OS has enabled support for saving YMM state.
Craig Topper1af7e442017-11-19 23:30:22 +00001501 Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1502 Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1503 Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
Simon Pilgrima271c542017-05-03 15:42:29 +00001504
Gabor Buellaa832b222018-05-10 07:26:05 +00001505 bool HasLeaf14 = MaxLevel >= 0x14 &&
1506 !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
1507
1508 Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
1509
Simon Pilgrima271c542017-05-03 15:42:29 +00001510 return true;
1511}
1512#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1513bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1514 std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1515 if (!P)
1516 return false;
1517
1518 SmallVector<StringRef, 32> Lines;
1519 P->getBuffer().split(Lines, "\n");
1520
1521 SmallVector<StringRef, 32> CPUFeatures;
1522
1523 // Look for the CPU features.
1524 for (unsigned I = 0, E = Lines.size(); I != E; ++I)
1525 if (Lines[I].startswith("Features")) {
1526 Lines[I].split(CPUFeatures, ' ');
1527 break;
1528 }
1529
1530#if defined(__aarch64__)
1531 // Keep track of which crypto features we have seen
1532 enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
1533 uint32_t crypto = 0;
1534#endif
1535
1536 for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
1537 StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
1538#if defined(__aarch64__)
1539 .Case("asimd", "neon")
1540 .Case("fp", "fp-armv8")
1541 .Case("crc32", "crc")
1542#else
1543 .Case("half", "fp16")
1544 .Case("neon", "neon")
1545 .Case("vfpv3", "vfp3")
1546 .Case("vfpv3d16", "d16")
1547 .Case("vfpv4", "vfp4")
1548 .Case("idiva", "hwdiv-arm")
1549 .Case("idivt", "hwdiv")
1550#endif
1551 .Default("");
1552
1553#if defined(__aarch64__)
1554 // We need to check crypto separately since we need all of the crypto
1555 // extensions to enable the subtarget feature
1556 if (CPUFeatures[I] == "aes")
1557 crypto |= CAP_AES;
1558 else if (CPUFeatures[I] == "pmull")
1559 crypto |= CAP_PMULL;
1560 else if (CPUFeatures[I] == "sha1")
1561 crypto |= CAP_SHA1;
1562 else if (CPUFeatures[I] == "sha2")
1563 crypto |= CAP_SHA2;
1564#endif
1565
1566 if (LLVMFeatureStr != "")
1567 Features[LLVMFeatureStr] = true;
1568 }
1569
1570#if defined(__aarch64__)
1571 // If we have all crypto bits we can add the feature
1572 if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
1573 Features["crypto"] = true;
1574#endif
1575
1576 return true;
1577}
Martin Storsjo353ac422019-10-02 11:04:55 +00001578#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
1579bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1580 if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
1581 Features["neon"] = true;
1582 if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
1583 Features["crc"] = true;
1584 if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
1585 Features["crypto"] = true;
1586
1587 return true;
1588}
Simon Pilgrima271c542017-05-03 15:42:29 +00001589#else
1590bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
1591#endif
1592
1593std::string sys::getProcessTriple() {
Alex Lorenz3803df32017-07-07 09:53:47 +00001594 std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
1595 Triple PT(Triple::normalize(TargetTripleString));
Simon Pilgrima271c542017-05-03 15:42:29 +00001596
1597 if (sizeof(void *) == 8 && PT.isArch32Bit())
1598 PT = PT.get64BitArchVariant();
1599 if (sizeof(void *) == 4 && PT.isArch64Bit())
1600 PT = PT.get32BitArchVariant();
1601
1602 return PT.str();
1603}