xref: /freebsd-src/contrib/llvm-project/llvm/lib/TargetParser/Host.cpp (revision c80e69b00d976a5a3b3e84527f270fa7e72a8205)
1bdd1243dSDimitry Andric //===-- Host.cpp - Implement OS Host Detection ------------------*- C++ -*-===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric //  This file implements the operating system Host detection.
10bdd1243dSDimitry Andric //
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "llvm/TargetParser/Host.h"
14bdd1243dSDimitry Andric #include "llvm/ADT/SmallVector.h"
15bdd1243dSDimitry Andric #include "llvm/ADT/StringMap.h"
16bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h"
17bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h"
18bdd1243dSDimitry Andric #include "llvm/Config/llvm-config.h"
19bdd1243dSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
20bdd1243dSDimitry Andric #include "llvm/Support/raw_ostream.h"
21bdd1243dSDimitry Andric #include "llvm/TargetParser/Triple.h"
22bdd1243dSDimitry Andric #include "llvm/TargetParser/X86TargetParser.h"
23bdd1243dSDimitry Andric #include <string.h>
24bdd1243dSDimitry Andric 
25bdd1243dSDimitry Andric // Include the platform-specific parts of this class.
26bdd1243dSDimitry Andric #ifdef LLVM_ON_UNIX
27bdd1243dSDimitry Andric #include "Unix/Host.inc"
28bdd1243dSDimitry Andric #include <sched.h>
29bdd1243dSDimitry Andric #endif
30bdd1243dSDimitry Andric #ifdef _WIN32
31bdd1243dSDimitry Andric #include "Windows/Host.inc"
32bdd1243dSDimitry Andric #endif
33bdd1243dSDimitry Andric #ifdef _MSC_VER
34bdd1243dSDimitry Andric #include <intrin.h>
35bdd1243dSDimitry Andric #endif
36bdd1243dSDimitry Andric #ifdef __MVS__
37bdd1243dSDimitry Andric #include "llvm/Support/BCD.h"
38bdd1243dSDimitry Andric #endif
39bdd1243dSDimitry Andric #if defined(__APPLE__)
40bdd1243dSDimitry Andric #include <mach/host_info.h>
41bdd1243dSDimitry Andric #include <mach/mach.h>
42bdd1243dSDimitry Andric #include <mach/mach_host.h>
43bdd1243dSDimitry Andric #include <mach/machine.h>
44bdd1243dSDimitry Andric #include <sys/param.h>
45bdd1243dSDimitry Andric #include <sys/sysctl.h>
46bdd1243dSDimitry Andric #endif
47bdd1243dSDimitry Andric #ifdef _AIX
48bdd1243dSDimitry Andric #include <sys/systemcfg.h>
49bdd1243dSDimitry Andric #endif
50bdd1243dSDimitry Andric #if defined(__sun__) && defined(__svr4__)
51bdd1243dSDimitry Andric #include <kstat.h>
52bdd1243dSDimitry Andric #endif
53bdd1243dSDimitry Andric 
54bdd1243dSDimitry Andric #define DEBUG_TYPE "host-detection"
55bdd1243dSDimitry Andric 
56bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
57bdd1243dSDimitry Andric //
58bdd1243dSDimitry Andric //  Implementations of the CPU detection routines
59bdd1243dSDimitry Andric //
60bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
61bdd1243dSDimitry Andric 
62bdd1243dSDimitry Andric using namespace llvm;
63bdd1243dSDimitry Andric 
64bdd1243dSDimitry Andric static std::unique_ptr<llvm::MemoryBuffer>
65bdd1243dSDimitry Andric     LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
66bdd1243dSDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
67bdd1243dSDimitry Andric       llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
68bdd1243dSDimitry Andric   if (std::error_code EC = Text.getError()) {
69bdd1243dSDimitry Andric     llvm::errs() << "Can't read "
70bdd1243dSDimitry Andric                  << "/proc/cpuinfo: " << EC.message() << "\n";
71bdd1243dSDimitry Andric     return nullptr;
72bdd1243dSDimitry Andric   }
73bdd1243dSDimitry Andric   return std::move(*Text);
74bdd1243dSDimitry Andric }
75bdd1243dSDimitry Andric 
76bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
77bdd1243dSDimitry Andric   // Access to the Processor Version Register (PVR) on PowerPC is privileged,
78bdd1243dSDimitry Andric   // and so we must use an operating-system interface to determine the current
79bdd1243dSDimitry Andric   // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
80bdd1243dSDimitry Andric   const char *generic = "generic";
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric   // The cpu line is second (after the 'processor: 0' line), so if this
83bdd1243dSDimitry Andric   // buffer is too small then something has changed (or is wrong).
84bdd1243dSDimitry Andric   StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
85bdd1243dSDimitry Andric   StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric   StringRef::const_iterator CIP = CPUInfoStart;
88bdd1243dSDimitry Andric 
89bdd1243dSDimitry Andric   StringRef::const_iterator CPUStart = nullptr;
90bdd1243dSDimitry Andric   size_t CPULen = 0;
91bdd1243dSDimitry Andric 
92bdd1243dSDimitry Andric   // We need to find the first line which starts with cpu, spaces, and a colon.
93bdd1243dSDimitry Andric   // After the colon, there may be some additional spaces and then the cpu type.
94bdd1243dSDimitry Andric   while (CIP < CPUInfoEnd && CPUStart == nullptr) {
95bdd1243dSDimitry Andric     if (CIP < CPUInfoEnd && *CIP == '\n')
96bdd1243dSDimitry Andric       ++CIP;
97bdd1243dSDimitry Andric 
98bdd1243dSDimitry Andric     if (CIP < CPUInfoEnd && *CIP == 'c') {
99bdd1243dSDimitry Andric       ++CIP;
100bdd1243dSDimitry Andric       if (CIP < CPUInfoEnd && *CIP == 'p') {
101bdd1243dSDimitry Andric         ++CIP;
102bdd1243dSDimitry Andric         if (CIP < CPUInfoEnd && *CIP == 'u') {
103bdd1243dSDimitry Andric           ++CIP;
104bdd1243dSDimitry Andric           while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
105bdd1243dSDimitry Andric             ++CIP;
106bdd1243dSDimitry Andric 
107bdd1243dSDimitry Andric           if (CIP < CPUInfoEnd && *CIP == ':') {
108bdd1243dSDimitry Andric             ++CIP;
109bdd1243dSDimitry Andric             while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
110bdd1243dSDimitry Andric               ++CIP;
111bdd1243dSDimitry Andric 
112bdd1243dSDimitry Andric             if (CIP < CPUInfoEnd) {
113bdd1243dSDimitry Andric               CPUStart = CIP;
114bdd1243dSDimitry Andric               while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
115bdd1243dSDimitry Andric                                           *CIP != ',' && *CIP != '\n'))
116bdd1243dSDimitry Andric                 ++CIP;
117bdd1243dSDimitry Andric               CPULen = CIP - CPUStart;
118bdd1243dSDimitry Andric             }
119bdd1243dSDimitry Andric           }
120bdd1243dSDimitry Andric         }
121bdd1243dSDimitry Andric       }
122bdd1243dSDimitry Andric     }
123bdd1243dSDimitry Andric 
124bdd1243dSDimitry Andric     if (CPUStart == nullptr)
125bdd1243dSDimitry Andric       while (CIP < CPUInfoEnd && *CIP != '\n')
126bdd1243dSDimitry Andric         ++CIP;
127bdd1243dSDimitry Andric   }
128bdd1243dSDimitry Andric 
129bdd1243dSDimitry Andric   if (CPUStart == nullptr)
130bdd1243dSDimitry Andric     return generic;
131bdd1243dSDimitry Andric 
132bdd1243dSDimitry Andric   return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
133bdd1243dSDimitry Andric       .Case("604e", "604e")
134bdd1243dSDimitry Andric       .Case("604", "604")
135bdd1243dSDimitry Andric       .Case("7400", "7400")
136bdd1243dSDimitry Andric       .Case("7410", "7400")
137bdd1243dSDimitry Andric       .Case("7447", "7400")
138bdd1243dSDimitry Andric       .Case("7455", "7450")
139bdd1243dSDimitry Andric       .Case("G4", "g4")
140bdd1243dSDimitry Andric       .Case("POWER4", "970")
141bdd1243dSDimitry Andric       .Case("PPC970FX", "970")
142bdd1243dSDimitry Andric       .Case("PPC970MP", "970")
143bdd1243dSDimitry Andric       .Case("G5", "g5")
144bdd1243dSDimitry Andric       .Case("POWER5", "g5")
145bdd1243dSDimitry Andric       .Case("A2", "a2")
146bdd1243dSDimitry Andric       .Case("POWER6", "pwr6")
147bdd1243dSDimitry Andric       .Case("POWER7", "pwr7")
148bdd1243dSDimitry Andric       .Case("POWER8", "pwr8")
149bdd1243dSDimitry Andric       .Case("POWER8E", "pwr8")
150bdd1243dSDimitry Andric       .Case("POWER8NVL", "pwr8")
151bdd1243dSDimitry Andric       .Case("POWER9", "pwr9")
152bdd1243dSDimitry Andric       .Case("POWER10", "pwr10")
15336b606aeSDimitry Andric       .Case("POWER11", "pwr11")
154bdd1243dSDimitry Andric       // FIXME: If we get a simulator or machine with the capabilities of
155bdd1243dSDimitry Andric       // mcpu=future, we should revisit this and add the name reported by the
156bdd1243dSDimitry Andric       // simulator/machine.
157bdd1243dSDimitry Andric       .Default(generic);
158bdd1243dSDimitry Andric }
159bdd1243dSDimitry Andric 
160bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
161bdd1243dSDimitry Andric   // The cpuid register on arm is not accessible from user space. On Linux,
162bdd1243dSDimitry Andric   // it is exposed through the /proc/cpuinfo file.
163bdd1243dSDimitry Andric 
164bdd1243dSDimitry Andric   // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
165bdd1243dSDimitry Andric   // in all cases.
166bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
167bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
168bdd1243dSDimitry Andric 
169bdd1243dSDimitry Andric   // Look for the CPU implementer line.
170bdd1243dSDimitry Andric   StringRef Implementer;
171bdd1243dSDimitry Andric   StringRef Hardware;
172bdd1243dSDimitry Andric   StringRef Part;
173bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
1745f757f3fSDimitry Andric     if (Lines[I].starts_with("CPU implementer"))
175bdd1243dSDimitry Andric       Implementer = Lines[I].substr(15).ltrim("\t :");
1765f757f3fSDimitry Andric     if (Lines[I].starts_with("Hardware"))
177bdd1243dSDimitry Andric       Hardware = Lines[I].substr(8).ltrim("\t :");
1785f757f3fSDimitry Andric     if (Lines[I].starts_with("CPU part"))
179bdd1243dSDimitry Andric       Part = Lines[I].substr(8).ltrim("\t :");
180bdd1243dSDimitry Andric   }
181bdd1243dSDimitry Andric 
182bdd1243dSDimitry Andric   if (Implementer == "0x41") { // ARM Ltd.
183bdd1243dSDimitry Andric     // MSM8992/8994 may give cpu part for the core that the kernel is running on,
184bdd1243dSDimitry Andric     // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
1855f757f3fSDimitry Andric     if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996"))
186bdd1243dSDimitry Andric       return "cortex-a53";
187bdd1243dSDimitry Andric 
188bdd1243dSDimitry Andric 
189bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
190bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
191bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
192bdd1243dSDimitry Andric     // This corresponds to the Main ID Register in Technical Reference Manuals.
193bdd1243dSDimitry Andric     // and is used in programs like sys-utils
194bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
195bdd1243dSDimitry Andric         .Case("0x926", "arm926ej-s")
196bdd1243dSDimitry Andric         .Case("0xb02", "mpcore")
197bdd1243dSDimitry Andric         .Case("0xb36", "arm1136j-s")
198bdd1243dSDimitry Andric         .Case("0xb56", "arm1156t2-s")
199bdd1243dSDimitry Andric         .Case("0xb76", "arm1176jz-s")
2000fca6ea1SDimitry Andric         .Case("0xc05", "cortex-a5")
2010fca6ea1SDimitry Andric         .Case("0xc07", "cortex-a7")
202bdd1243dSDimitry Andric         .Case("0xc08", "cortex-a8")
203bdd1243dSDimitry Andric         .Case("0xc09", "cortex-a9")
204bdd1243dSDimitry Andric         .Case("0xc0f", "cortex-a15")
2050fca6ea1SDimitry Andric         .Case("0xc0e", "cortex-a17")
206bdd1243dSDimitry Andric         .Case("0xc20", "cortex-m0")
207bdd1243dSDimitry Andric         .Case("0xc23", "cortex-m3")
208bdd1243dSDimitry Andric         .Case("0xc24", "cortex-m4")
2090fca6ea1SDimitry Andric         .Case("0xc27", "cortex-m7")
2100fca6ea1SDimitry Andric         .Case("0xd20", "cortex-m23")
2110fca6ea1SDimitry Andric         .Case("0xd21", "cortex-m33")
2125f757f3fSDimitry Andric         .Case("0xd24", "cortex-m52")
213bdd1243dSDimitry Andric         .Case("0xd22", "cortex-m55")
2140fca6ea1SDimitry Andric         .Case("0xd23", "cortex-m85")
2150fca6ea1SDimitry Andric         .Case("0xc18", "cortex-r8")
2160fca6ea1SDimitry Andric         .Case("0xd13", "cortex-r52")
2170fca6ea1SDimitry Andric         .Case("0xd16", "cortex-r52plus")
2180fca6ea1SDimitry Andric         .Case("0xd15", "cortex-r82")
2190fca6ea1SDimitry Andric         .Case("0xd14", "cortex-r82ae")
220bdd1243dSDimitry Andric         .Case("0xd02", "cortex-a34")
221bdd1243dSDimitry Andric         .Case("0xd04", "cortex-a35")
222bdd1243dSDimitry Andric         .Case("0xd03", "cortex-a53")
223bdd1243dSDimitry Andric         .Case("0xd05", "cortex-a55")
224bdd1243dSDimitry Andric         .Case("0xd46", "cortex-a510")
2255f757f3fSDimitry Andric         .Case("0xd80", "cortex-a520")
2260fca6ea1SDimitry Andric         .Case("0xd88", "cortex-a520ae")
227bdd1243dSDimitry Andric         .Case("0xd07", "cortex-a57")
2280fca6ea1SDimitry Andric         .Case("0xd06", "cortex-a65")
2290fca6ea1SDimitry Andric         .Case("0xd43", "cortex-a65ae")
230bdd1243dSDimitry Andric         .Case("0xd08", "cortex-a72")
231bdd1243dSDimitry Andric         .Case("0xd09", "cortex-a73")
232bdd1243dSDimitry Andric         .Case("0xd0a", "cortex-a75")
233bdd1243dSDimitry Andric         .Case("0xd0b", "cortex-a76")
2340fca6ea1SDimitry Andric         .Case("0xd0e", "cortex-a76ae")
235bdd1243dSDimitry Andric         .Case("0xd0d", "cortex-a77")
236bdd1243dSDimitry Andric         .Case("0xd41", "cortex-a78")
2370fca6ea1SDimitry Andric         .Case("0xd42", "cortex-a78ae")
2380fca6ea1SDimitry Andric         .Case("0xd4b", "cortex-a78c")
239bdd1243dSDimitry Andric         .Case("0xd47", "cortex-a710")
240bdd1243dSDimitry Andric         .Case("0xd4d", "cortex-a715")
2415f757f3fSDimitry Andric         .Case("0xd81", "cortex-a720")
2420fca6ea1SDimitry Andric         .Case("0xd89", "cortex-a720ae")
2430fca6ea1SDimitry Andric         .Case("0xd87", "cortex-a725")
244bdd1243dSDimitry Andric         .Case("0xd44", "cortex-x1")
245bdd1243dSDimitry Andric         .Case("0xd4c", "cortex-x1c")
246bdd1243dSDimitry Andric         .Case("0xd48", "cortex-x2")
247bdd1243dSDimitry Andric         .Case("0xd4e", "cortex-x3")
2485f757f3fSDimitry Andric         .Case("0xd82", "cortex-x4")
2490fca6ea1SDimitry Andric         .Case("0xd85", "cortex-x925")
2500fca6ea1SDimitry Andric         .Case("0xd4a", "neoverse-e1")
251bdd1243dSDimitry Andric         .Case("0xd0c", "neoverse-n1")
252bdd1243dSDimitry Andric         .Case("0xd49", "neoverse-n2")
2530fca6ea1SDimitry Andric         .Case("0xd8e", "neoverse-n3")
254bdd1243dSDimitry Andric         .Case("0xd40", "neoverse-v1")
255bdd1243dSDimitry Andric         .Case("0xd4f", "neoverse-v2")
2560fca6ea1SDimitry Andric         .Case("0xd84", "neoverse-v3")
2570fca6ea1SDimitry Andric         .Case("0xd83", "neoverse-v3ae")
258bdd1243dSDimitry Andric         .Default("generic");
259bdd1243dSDimitry Andric   }
260bdd1243dSDimitry Andric 
261bdd1243dSDimitry Andric   if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
262bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
263bdd1243dSDimitry Andric       .Case("0x516", "thunderx2t99")
264bdd1243dSDimitry Andric       .Case("0x0516", "thunderx2t99")
265bdd1243dSDimitry Andric       .Case("0xaf", "thunderx2t99")
266bdd1243dSDimitry Andric       .Case("0x0af", "thunderx2t99")
267bdd1243dSDimitry Andric       .Case("0xa1", "thunderxt88")
268bdd1243dSDimitry Andric       .Case("0x0a1", "thunderxt88")
269bdd1243dSDimitry Andric       .Default("generic");
270bdd1243dSDimitry Andric   }
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric   if (Implementer == "0x46") { // Fujitsu Ltd.
273bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
274bdd1243dSDimitry Andric       .Case("0x001", "a64fx")
275bdd1243dSDimitry Andric       .Default("generic");
276bdd1243dSDimitry Andric   }
277bdd1243dSDimitry Andric 
278bdd1243dSDimitry Andric   if (Implementer == "0x4e") { // NVIDIA Corporation
279bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
280bdd1243dSDimitry Andric         .Case("0x004", "carmel")
281bdd1243dSDimitry Andric         .Default("generic");
282bdd1243dSDimitry Andric   }
283bdd1243dSDimitry Andric 
284bdd1243dSDimitry Andric   if (Implementer == "0x48") // HiSilicon Technologies, Inc.
285bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
286bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
287bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
288bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
289bdd1243dSDimitry Andric       .Case("0xd01", "tsv110")
290bdd1243dSDimitry Andric       .Default("generic");
291bdd1243dSDimitry Andric 
292bdd1243dSDimitry Andric   if (Implementer == "0x51") // Qualcomm Technologies, Inc.
293bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
294bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
295bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
296bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
297bdd1243dSDimitry Andric         .Case("0x06f", "krait") // APQ8064
298bdd1243dSDimitry Andric         .Case("0x201", "kryo")
299bdd1243dSDimitry Andric         .Case("0x205", "kryo")
300bdd1243dSDimitry Andric         .Case("0x211", "kryo")
301bdd1243dSDimitry Andric         .Case("0x800", "cortex-a73") // Kryo 2xx Gold
302bdd1243dSDimitry Andric         .Case("0x801", "cortex-a73") // Kryo 2xx Silver
303bdd1243dSDimitry Andric         .Case("0x802", "cortex-a75") // Kryo 3xx Gold
304bdd1243dSDimitry Andric         .Case("0x803", "cortex-a75") // Kryo 3xx Silver
305bdd1243dSDimitry Andric         .Case("0x804", "cortex-a76") // Kryo 4xx Gold
306bdd1243dSDimitry Andric         .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver
307bdd1243dSDimitry Andric         .Case("0xc00", "falkor")
308bdd1243dSDimitry Andric         .Case("0xc01", "saphira")
3090fca6ea1SDimitry Andric         .Case("0x001", "oryon-1")
310bdd1243dSDimitry Andric         .Default("generic");
311bdd1243dSDimitry Andric   if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
312bdd1243dSDimitry Andric     // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
313bdd1243dSDimitry Andric     // any predictive pattern across variants and parts.
314bdd1243dSDimitry Andric     unsigned Variant = 0, Part = 0;
315bdd1243dSDimitry Andric 
316bdd1243dSDimitry Andric     // Look for the CPU variant line, whose value is a 1 digit hexadecimal
317bdd1243dSDimitry Andric     // number, corresponding to the Variant bits in the CP15/C0 register.
318bdd1243dSDimitry Andric     for (auto I : Lines)
319bdd1243dSDimitry Andric       if (I.consume_front("CPU variant"))
320bdd1243dSDimitry Andric         I.ltrim("\t :").getAsInteger(0, Variant);
321bdd1243dSDimitry Andric 
322bdd1243dSDimitry Andric     // Look for the CPU part line, whose value is a 3 digit hexadecimal
323bdd1243dSDimitry Andric     // number, corresponding to the PartNum bits in the CP15/C0 register.
324bdd1243dSDimitry Andric     for (auto I : Lines)
325bdd1243dSDimitry Andric       if (I.consume_front("CPU part"))
326bdd1243dSDimitry Andric         I.ltrim("\t :").getAsInteger(0, Part);
327bdd1243dSDimitry Andric 
328bdd1243dSDimitry Andric     unsigned Exynos = (Variant << 12) | Part;
329bdd1243dSDimitry Andric     switch (Exynos) {
330bdd1243dSDimitry Andric     default:
331bdd1243dSDimitry Andric       // Default by falling through to Exynos M3.
332bdd1243dSDimitry Andric       [[fallthrough]];
333bdd1243dSDimitry Andric     case 0x1002:
334bdd1243dSDimitry Andric       return "exynos-m3";
335bdd1243dSDimitry Andric     case 0x1003:
336bdd1243dSDimitry Andric       return "exynos-m4";
337bdd1243dSDimitry Andric     }
338bdd1243dSDimitry Andric   }
339bdd1243dSDimitry Andric 
3407a6dacacSDimitry Andric   if (Implementer == "0x6d") { // Microsoft Corporation.
3417a6dacacSDimitry Andric     // The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2.
3427a6dacacSDimitry Andric     return StringSwitch<const char *>(Part)
3437a6dacacSDimitry Andric         .Case("0xd49", "neoverse-n2")
3447a6dacacSDimitry Andric         .Default("generic");
3457a6dacacSDimitry Andric   }
3467a6dacacSDimitry Andric 
347bdd1243dSDimitry Andric   if (Implementer == "0xc0") { // Ampere Computing
348bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
349bdd1243dSDimitry Andric         .Case("0xac3", "ampere1")
350bdd1243dSDimitry Andric         .Case("0xac4", "ampere1a")
3514c2d3b02SDimitry Andric         .Case("0xac5", "ampere1b")
352bdd1243dSDimitry Andric         .Default("generic");
353bdd1243dSDimitry Andric   }
354bdd1243dSDimitry Andric 
355bdd1243dSDimitry Andric   return "generic";
356bdd1243dSDimitry Andric }
357bdd1243dSDimitry Andric 
358bdd1243dSDimitry Andric namespace {
359bdd1243dSDimitry Andric StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {
360bdd1243dSDimitry Andric   switch (Id) {
361bdd1243dSDimitry Andric     case 2064:  // z900 not supported by LLVM
362bdd1243dSDimitry Andric     case 2066:
363bdd1243dSDimitry Andric     case 2084:  // z990 not supported by LLVM
364bdd1243dSDimitry Andric     case 2086:
365bdd1243dSDimitry Andric     case 2094:  // z9-109 not supported by LLVM
366bdd1243dSDimitry Andric     case 2096:
367bdd1243dSDimitry Andric       return "generic";
368bdd1243dSDimitry Andric     case 2097:
369bdd1243dSDimitry Andric     case 2098:
370bdd1243dSDimitry Andric       return "z10";
371bdd1243dSDimitry Andric     case 2817:
372bdd1243dSDimitry Andric     case 2818:
373bdd1243dSDimitry Andric       return "z196";
374bdd1243dSDimitry Andric     case 2827:
375bdd1243dSDimitry Andric     case 2828:
376bdd1243dSDimitry Andric       return "zEC12";
377bdd1243dSDimitry Andric     case 2964:
378bdd1243dSDimitry Andric     case 2965:
379bdd1243dSDimitry Andric       return HaveVectorSupport? "z13" : "zEC12";
380bdd1243dSDimitry Andric     case 3906:
381bdd1243dSDimitry Andric     case 3907:
382bdd1243dSDimitry Andric       return HaveVectorSupport? "z14" : "zEC12";
383bdd1243dSDimitry Andric     case 8561:
384bdd1243dSDimitry Andric     case 8562:
385bdd1243dSDimitry Andric       return HaveVectorSupport? "z15" : "zEC12";
386bdd1243dSDimitry Andric     case 3931:
387bdd1243dSDimitry Andric     case 3932:
388bdd1243dSDimitry Andric     default:
389bdd1243dSDimitry Andric       return HaveVectorSupport? "z16" : "zEC12";
390bdd1243dSDimitry Andric   }
391bdd1243dSDimitry Andric }
392bdd1243dSDimitry Andric } // end anonymous namespace
393bdd1243dSDimitry Andric 
394bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
395bdd1243dSDimitry Andric   // STIDP is a privileged operation, so use /proc/cpuinfo instead.
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric   // The "processor 0:" line comes after a fair amount of other information,
398bdd1243dSDimitry Andric   // including a cache breakdown, but this should be plenty.
399bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
400bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
401bdd1243dSDimitry Andric 
402bdd1243dSDimitry Andric   // Look for the CPU features.
403bdd1243dSDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
404bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
4055f757f3fSDimitry Andric     if (Lines[I].starts_with("features")) {
406bdd1243dSDimitry Andric       size_t Pos = Lines[I].find(':');
407bdd1243dSDimitry Andric       if (Pos != StringRef::npos) {
408bdd1243dSDimitry Andric         Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
409bdd1243dSDimitry Andric         break;
410bdd1243dSDimitry Andric       }
411bdd1243dSDimitry Andric     }
412bdd1243dSDimitry Andric 
413bdd1243dSDimitry Andric   // We need to check for the presence of vector support independently of
414bdd1243dSDimitry Andric   // the machine type, since we may only use the vector register set when
415bdd1243dSDimitry Andric   // supported by the kernel (and hypervisor).
416bdd1243dSDimitry Andric   bool HaveVectorSupport = false;
417bdd1243dSDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
418bdd1243dSDimitry Andric     if (CPUFeatures[I] == "vx")
419bdd1243dSDimitry Andric       HaveVectorSupport = true;
420bdd1243dSDimitry Andric   }
421bdd1243dSDimitry Andric 
422bdd1243dSDimitry Andric   // Now check the processor machine type.
423bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
4245f757f3fSDimitry Andric     if (Lines[I].starts_with("processor ")) {
425bdd1243dSDimitry Andric       size_t Pos = Lines[I].find("machine = ");
426bdd1243dSDimitry Andric       if (Pos != StringRef::npos) {
427bdd1243dSDimitry Andric         Pos += sizeof("machine = ") - 1;
428bdd1243dSDimitry Andric         unsigned int Id;
429bdd1243dSDimitry Andric         if (!Lines[I].drop_front(Pos).getAsInteger(10, Id))
430bdd1243dSDimitry Andric           return getCPUNameFromS390Model(Id, HaveVectorSupport);
431bdd1243dSDimitry Andric       }
432bdd1243dSDimitry Andric       break;
433bdd1243dSDimitry Andric     }
434bdd1243dSDimitry Andric   }
435bdd1243dSDimitry Andric 
436bdd1243dSDimitry Andric   return "generic";
437bdd1243dSDimitry Andric }
438bdd1243dSDimitry Andric 
439bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {
440bdd1243dSDimitry Andric   // There are 24 lines in /proc/cpuinfo
441bdd1243dSDimitry Andric   SmallVector<StringRef> Lines;
442bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
443bdd1243dSDimitry Andric 
444bdd1243dSDimitry Andric   // Look for uarch line to determine cpu name
445bdd1243dSDimitry Andric   StringRef UArch;
446bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
4475f757f3fSDimitry Andric     if (Lines[I].starts_with("uarch")) {
448bdd1243dSDimitry Andric       UArch = Lines[I].substr(5).ltrim("\t :");
449bdd1243dSDimitry Andric       break;
450bdd1243dSDimitry Andric     }
451bdd1243dSDimitry Andric   }
452bdd1243dSDimitry Andric 
453bdd1243dSDimitry Andric   return StringSwitch<const char *>(UArch)
454bdd1243dSDimitry Andric       .Case("sifive,u74-mc", "sifive-u74")
455bdd1243dSDimitry Andric       .Case("sifive,bullet0", "sifive-u74")
4560fca6ea1SDimitry Andric       .Default("");
457bdd1243dSDimitry Andric }
458bdd1243dSDimitry Andric 
459bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForBPF() {
460bdd1243dSDimitry Andric #if !defined(__linux__) || !defined(__x86_64__)
461bdd1243dSDimitry Andric   return "generic";
462bdd1243dSDimitry Andric #else
463bdd1243dSDimitry Andric   uint8_t v3_insns[40] __attribute__ ((aligned (8))) =
464bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
465bdd1243dSDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
466bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
467bdd1243dSDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
468bdd1243dSDimitry Andric       /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
469bdd1243dSDimitry Andric       0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
470bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
471bdd1243dSDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
472bdd1243dSDimitry Andric       /* BPF_EXIT_INSN() */
473bdd1243dSDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
474bdd1243dSDimitry Andric 
475bdd1243dSDimitry Andric   uint8_t v2_insns[40] __attribute__ ((aligned (8))) =
476bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
477bdd1243dSDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
478bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
479bdd1243dSDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
480bdd1243dSDimitry Andric       /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
481bdd1243dSDimitry Andric       0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
482bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
483bdd1243dSDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
484bdd1243dSDimitry Andric       /* BPF_EXIT_INSN() */
485bdd1243dSDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
486bdd1243dSDimitry Andric 
487bdd1243dSDimitry Andric   struct bpf_prog_load_attr {
488bdd1243dSDimitry Andric     uint32_t prog_type;
489bdd1243dSDimitry Andric     uint32_t insn_cnt;
490bdd1243dSDimitry Andric     uint64_t insns;
491bdd1243dSDimitry Andric     uint64_t license;
492bdd1243dSDimitry Andric     uint32_t log_level;
493bdd1243dSDimitry Andric     uint32_t log_size;
494bdd1243dSDimitry Andric     uint64_t log_buf;
495bdd1243dSDimitry Andric     uint32_t kern_version;
496bdd1243dSDimitry Andric     uint32_t prog_flags;
497bdd1243dSDimitry Andric   } attr = {};
498bdd1243dSDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
499bdd1243dSDimitry Andric   attr.insn_cnt = 5;
500bdd1243dSDimitry Andric   attr.insns = (uint64_t)v3_insns;
501bdd1243dSDimitry Andric   attr.license = (uint64_t)"DUMMY";
502bdd1243dSDimitry Andric 
503bdd1243dSDimitry Andric   int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,
504bdd1243dSDimitry Andric                    sizeof(attr));
505bdd1243dSDimitry Andric   if (fd >= 0) {
506bdd1243dSDimitry Andric     close(fd);
507bdd1243dSDimitry Andric     return "v3";
508bdd1243dSDimitry Andric   }
509bdd1243dSDimitry Andric 
510bdd1243dSDimitry Andric   /* Clear the whole attr in case its content changed by syscall. */
511bdd1243dSDimitry Andric   memset(&attr, 0, sizeof(attr));
512bdd1243dSDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
513bdd1243dSDimitry Andric   attr.insn_cnt = 5;
514bdd1243dSDimitry Andric   attr.insns = (uint64_t)v2_insns;
515bdd1243dSDimitry Andric   attr.license = (uint64_t)"DUMMY";
516bdd1243dSDimitry Andric   fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
517bdd1243dSDimitry Andric   if (fd >= 0) {
518bdd1243dSDimitry Andric     close(fd);
519bdd1243dSDimitry Andric     return "v2";
520bdd1243dSDimitry Andric   }
521bdd1243dSDimitry Andric   return "v1";
522bdd1243dSDimitry Andric #endif
523bdd1243dSDimitry Andric }
524bdd1243dSDimitry Andric 
525bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
526bdd1243dSDimitry Andric     defined(__x86_64__) || defined(_M_X64)
527bdd1243dSDimitry Andric 
528bdd1243dSDimitry Andric // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
529bdd1243dSDimitry Andric // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
530bdd1243dSDimitry Andric // support. Consequently, for i386, the presence of CPUID is checked first
531bdd1243dSDimitry Andric // via the corresponding eflags bit.
532bdd1243dSDimitry Andric // Removal of cpuid.h header motivated by PR30384
533bdd1243dSDimitry Andric // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
534bdd1243dSDimitry Andric // or test-suite, but are used in external projects e.g. libstdcxx
535bdd1243dSDimitry Andric static bool isCpuIdSupported() {
536bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
537bdd1243dSDimitry Andric #if defined(__i386__)
538bdd1243dSDimitry Andric   int __cpuid_supported;
539bdd1243dSDimitry Andric   __asm__("  pushfl\n"
540bdd1243dSDimitry Andric           "  popl   %%eax\n"
541bdd1243dSDimitry Andric           "  movl   %%eax,%%ecx\n"
542bdd1243dSDimitry Andric           "  xorl   $0x00200000,%%eax\n"
543bdd1243dSDimitry Andric           "  pushl  %%eax\n"
544bdd1243dSDimitry Andric           "  popfl\n"
545bdd1243dSDimitry Andric           "  pushfl\n"
546bdd1243dSDimitry Andric           "  popl   %%eax\n"
547bdd1243dSDimitry Andric           "  movl   $0,%0\n"
548bdd1243dSDimitry Andric           "  cmpl   %%eax,%%ecx\n"
549bdd1243dSDimitry Andric           "  je     1f\n"
550bdd1243dSDimitry Andric           "  movl   $1,%0\n"
551bdd1243dSDimitry Andric           "1:"
552bdd1243dSDimitry Andric           : "=r"(__cpuid_supported)
553bdd1243dSDimitry Andric           :
554bdd1243dSDimitry Andric           : "eax", "ecx");
555bdd1243dSDimitry Andric   if (!__cpuid_supported)
556bdd1243dSDimitry Andric     return false;
557bdd1243dSDimitry Andric #endif
558bdd1243dSDimitry Andric   return true;
559bdd1243dSDimitry Andric #endif
560bdd1243dSDimitry Andric   return true;
561bdd1243dSDimitry Andric }
562bdd1243dSDimitry Andric 
563bdd1243dSDimitry Andric /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
564bdd1243dSDimitry Andric /// the specified arguments.  If we can't run cpuid on the host, return true.
565bdd1243dSDimitry Andric static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
566bdd1243dSDimitry Andric                                unsigned *rECX, unsigned *rEDX) {
567bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
568bdd1243dSDimitry Andric #if defined(__x86_64__)
569bdd1243dSDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
570bdd1243dSDimitry Andric   // FIXME: should we save this for Clang?
571bdd1243dSDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
572bdd1243dSDimitry Andric           "cpuid\n\t"
573bdd1243dSDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
574bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
575bdd1243dSDimitry Andric           : "a"(value));
576bdd1243dSDimitry Andric   return false;
577bdd1243dSDimitry Andric #elif defined(__i386__)
578bdd1243dSDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
579bdd1243dSDimitry Andric           "cpuid\n\t"
580bdd1243dSDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
581bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
582bdd1243dSDimitry Andric           : "a"(value));
583bdd1243dSDimitry Andric   return false;
584bdd1243dSDimitry Andric #else
585bdd1243dSDimitry Andric   return true;
586bdd1243dSDimitry Andric #endif
587bdd1243dSDimitry Andric #elif defined(_MSC_VER)
588bdd1243dSDimitry Andric   // The MSVC intrinsic is portable across x86 and x64.
589bdd1243dSDimitry Andric   int registers[4];
590bdd1243dSDimitry Andric   __cpuid(registers, value);
591bdd1243dSDimitry Andric   *rEAX = registers[0];
592bdd1243dSDimitry Andric   *rEBX = registers[1];
593bdd1243dSDimitry Andric   *rECX = registers[2];
594bdd1243dSDimitry Andric   *rEDX = registers[3];
595bdd1243dSDimitry Andric   return false;
596bdd1243dSDimitry Andric #else
597bdd1243dSDimitry Andric   return true;
598bdd1243dSDimitry Andric #endif
599bdd1243dSDimitry Andric }
600bdd1243dSDimitry Andric 
601bdd1243dSDimitry Andric namespace llvm {
602bdd1243dSDimitry Andric namespace sys {
603bdd1243dSDimitry Andric namespace detail {
604bdd1243dSDimitry Andric namespace x86 {
605bdd1243dSDimitry Andric 
606bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
607bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
608bdd1243dSDimitry Andric   if (MaxLeaf == nullptr)
609bdd1243dSDimitry Andric     MaxLeaf = &EAX;
610bdd1243dSDimitry Andric   else
611bdd1243dSDimitry Andric     *MaxLeaf = 0;
612bdd1243dSDimitry Andric 
613bdd1243dSDimitry Andric   if (!isCpuIdSupported())
614bdd1243dSDimitry Andric     return VendorSignatures::UNKNOWN;
615bdd1243dSDimitry Andric 
616bdd1243dSDimitry Andric   if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)
617bdd1243dSDimitry Andric     return VendorSignatures::UNKNOWN;
618bdd1243dSDimitry Andric 
619bdd1243dSDimitry Andric   // "Genu ineI ntel"
620bdd1243dSDimitry Andric   if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)
621bdd1243dSDimitry Andric     return VendorSignatures::GENUINE_INTEL;
622bdd1243dSDimitry Andric 
623bdd1243dSDimitry Andric   // "Auth enti cAMD"
624bdd1243dSDimitry Andric   if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)
625bdd1243dSDimitry Andric     return VendorSignatures::AUTHENTIC_AMD;
626bdd1243dSDimitry Andric 
627bdd1243dSDimitry Andric   return VendorSignatures::UNKNOWN;
628bdd1243dSDimitry Andric }
629bdd1243dSDimitry Andric 
630bdd1243dSDimitry Andric } // namespace x86
631bdd1243dSDimitry Andric } // namespace detail
632bdd1243dSDimitry Andric } // namespace sys
633bdd1243dSDimitry Andric } // namespace llvm
634bdd1243dSDimitry Andric 
635bdd1243dSDimitry Andric using namespace llvm::sys::detail::x86;
636bdd1243dSDimitry Andric 
637bdd1243dSDimitry Andric /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
638bdd1243dSDimitry Andric /// the 4 values in the specified arguments.  If we can't run cpuid on the host,
639bdd1243dSDimitry Andric /// return true.
640bdd1243dSDimitry Andric static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
641bdd1243dSDimitry Andric                                  unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
642bdd1243dSDimitry Andric                                  unsigned *rEDX) {
643bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
644bdd1243dSDimitry Andric #if defined(__x86_64__)
645bdd1243dSDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
646bdd1243dSDimitry Andric   // FIXME: should we save this for Clang?
647bdd1243dSDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
648bdd1243dSDimitry Andric           "cpuid\n\t"
649bdd1243dSDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
650bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
651bdd1243dSDimitry Andric           : "a"(value), "c"(subleaf));
652bdd1243dSDimitry Andric   return false;
653bdd1243dSDimitry Andric #elif defined(__i386__)
654bdd1243dSDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
655bdd1243dSDimitry Andric           "cpuid\n\t"
656bdd1243dSDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
657bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
658bdd1243dSDimitry Andric           : "a"(value), "c"(subleaf));
659bdd1243dSDimitry Andric   return false;
660bdd1243dSDimitry Andric #else
661bdd1243dSDimitry Andric   return true;
662bdd1243dSDimitry Andric #endif
663bdd1243dSDimitry Andric #elif defined(_MSC_VER)
664bdd1243dSDimitry Andric   int registers[4];
665bdd1243dSDimitry Andric   __cpuidex(registers, value, subleaf);
666bdd1243dSDimitry Andric   *rEAX = registers[0];
667bdd1243dSDimitry Andric   *rEBX = registers[1];
668bdd1243dSDimitry Andric   *rECX = registers[2];
669bdd1243dSDimitry Andric   *rEDX = registers[3];
670bdd1243dSDimitry Andric   return false;
671bdd1243dSDimitry Andric #else
672bdd1243dSDimitry Andric   return true;
673bdd1243dSDimitry Andric #endif
674bdd1243dSDimitry Andric }
675bdd1243dSDimitry Andric 
676bdd1243dSDimitry Andric // Read control register 0 (XCR0). Used to detect features such as AVX.
677bdd1243dSDimitry Andric static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
678bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
679bdd1243dSDimitry Andric   // Check xgetbv; this uses a .byte sequence instead of the instruction
680bdd1243dSDimitry Andric   // directly because older assemblers do not include support for xgetbv and
681bdd1243dSDimitry Andric   // there is no easy way to conditionally compile based on the assembler used.
682bdd1243dSDimitry Andric   __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
683bdd1243dSDimitry Andric   return false;
684bdd1243dSDimitry Andric #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
685bdd1243dSDimitry Andric   unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
686bdd1243dSDimitry Andric   *rEAX = Result;
687bdd1243dSDimitry Andric   *rEDX = Result >> 32;
688bdd1243dSDimitry Andric   return false;
689bdd1243dSDimitry Andric #else
690bdd1243dSDimitry Andric   return true;
691bdd1243dSDimitry Andric #endif
692bdd1243dSDimitry Andric }
693bdd1243dSDimitry Andric 
694bdd1243dSDimitry Andric static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
695bdd1243dSDimitry Andric                                  unsigned *Model) {
696bdd1243dSDimitry Andric   *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
697bdd1243dSDimitry Andric   *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
698bdd1243dSDimitry Andric   if (*Family == 6 || *Family == 0xf) {
699bdd1243dSDimitry Andric     if (*Family == 0xf)
700bdd1243dSDimitry Andric       // Examine extended family ID if family ID is F.
701bdd1243dSDimitry Andric       *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
702bdd1243dSDimitry Andric     // Examine extended model ID if family ID is 6 or F.
703bdd1243dSDimitry Andric     *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
704bdd1243dSDimitry Andric   }
705bdd1243dSDimitry Andric }
706bdd1243dSDimitry Andric 
7070fca6ea1SDimitry Andric #define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
708bdd1243dSDimitry Andric 
7090fca6ea1SDimitry Andric static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,
7100fca6ea1SDimitry Andric                                                  unsigned Model,
7110fca6ea1SDimitry Andric                                                  const unsigned *Features,
7120fca6ea1SDimitry Andric                                                  unsigned *Type,
7130fca6ea1SDimitry Andric                                                  unsigned *Subtype) {
714bdd1243dSDimitry Andric   StringRef CPU;
715bdd1243dSDimitry Andric 
716bdd1243dSDimitry Andric   switch (Family) {
717bdd1243dSDimitry Andric   case 3:
718bdd1243dSDimitry Andric     CPU = "i386";
719bdd1243dSDimitry Andric     break;
720bdd1243dSDimitry Andric   case 4:
721bdd1243dSDimitry Andric     CPU = "i486";
722bdd1243dSDimitry Andric     break;
723bdd1243dSDimitry Andric   case 5:
724bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_MMX)) {
725bdd1243dSDimitry Andric       CPU = "pentium-mmx";
726bdd1243dSDimitry Andric       break;
727bdd1243dSDimitry Andric     }
728bdd1243dSDimitry Andric     CPU = "pentium";
729bdd1243dSDimitry Andric     break;
730bdd1243dSDimitry Andric   case 6:
731bdd1243dSDimitry Andric     switch (Model) {
732bdd1243dSDimitry Andric     case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
733bdd1243dSDimitry Andric                // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
734bdd1243dSDimitry Andric                // mobile processor, Intel Core 2 Extreme processor, Intel
735bdd1243dSDimitry Andric                // Pentium Dual-Core processor, Intel Xeon processor, model
736bdd1243dSDimitry Andric                // 0Fh. All processors are manufactured using the 65 nm process.
737bdd1243dSDimitry Andric     case 0x16: // Intel Celeron processor model 16h. All processors are
738bdd1243dSDimitry Andric                // manufactured using the 65 nm process
739bdd1243dSDimitry Andric       CPU = "core2";
740bdd1243dSDimitry Andric       *Type = X86::INTEL_CORE2;
741bdd1243dSDimitry Andric       break;
742bdd1243dSDimitry Andric     case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
743bdd1243dSDimitry Andric                // 17h. All processors are manufactured using the 45 nm process.
744bdd1243dSDimitry Andric                //
745bdd1243dSDimitry Andric                // 45nm: Penryn , Wolfdale, Yorkfield (XE)
746bdd1243dSDimitry Andric     case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
747bdd1243dSDimitry Andric                // the 45 nm process.
748bdd1243dSDimitry Andric       CPU = "penryn";
749bdd1243dSDimitry Andric       *Type = X86::INTEL_CORE2;
750bdd1243dSDimitry Andric       break;
751bdd1243dSDimitry Andric     case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
752bdd1243dSDimitry Andric                // processors are manufactured using the 45 nm process.
753bdd1243dSDimitry Andric     case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
754bdd1243dSDimitry Andric                // As found in a Summer 2010 model iMac.
755bdd1243dSDimitry Andric     case 0x1f:
756bdd1243dSDimitry Andric     case 0x2e:              // Nehalem EX
757bdd1243dSDimitry Andric       CPU = "nehalem";
758bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
759bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_NEHALEM;
760bdd1243dSDimitry Andric       break;
761bdd1243dSDimitry Andric     case 0x25: // Intel Core i7, laptop version.
762bdd1243dSDimitry Andric     case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
763bdd1243dSDimitry Andric                // processors are manufactured using the 32 nm process.
764bdd1243dSDimitry Andric     case 0x2f: // Westmere EX
765bdd1243dSDimitry Andric       CPU = "westmere";
766bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
767bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_WESTMERE;
768bdd1243dSDimitry Andric       break;
769bdd1243dSDimitry Andric     case 0x2a: // Intel Core i7 processor. All processors are manufactured
770bdd1243dSDimitry Andric                // using the 32 nm process.
771bdd1243dSDimitry Andric     case 0x2d:
772bdd1243dSDimitry Andric       CPU = "sandybridge";
773bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
774bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
775bdd1243dSDimitry Andric       break;
776bdd1243dSDimitry Andric     case 0x3a:
777bdd1243dSDimitry Andric     case 0x3e:              // Ivy Bridge EP
778bdd1243dSDimitry Andric       CPU = "ivybridge";
779bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
780bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
781bdd1243dSDimitry Andric       break;
782bdd1243dSDimitry Andric 
783bdd1243dSDimitry Andric     // Haswell:
784bdd1243dSDimitry Andric     case 0x3c:
785bdd1243dSDimitry Andric     case 0x3f:
786bdd1243dSDimitry Andric     case 0x45:
787bdd1243dSDimitry Andric     case 0x46:
788bdd1243dSDimitry Andric       CPU = "haswell";
789bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
790bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_HASWELL;
791bdd1243dSDimitry Andric       break;
792bdd1243dSDimitry Andric 
793bdd1243dSDimitry Andric     // Broadwell:
794bdd1243dSDimitry Andric     case 0x3d:
795bdd1243dSDimitry Andric     case 0x47:
796bdd1243dSDimitry Andric     case 0x4f:
797bdd1243dSDimitry Andric     case 0x56:
798bdd1243dSDimitry Andric       CPU = "broadwell";
799bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
800bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_BROADWELL;
801bdd1243dSDimitry Andric       break;
802bdd1243dSDimitry Andric 
803bdd1243dSDimitry Andric     // Skylake:
804bdd1243dSDimitry Andric     case 0x4e:              // Skylake mobile
805bdd1243dSDimitry Andric     case 0x5e:              // Skylake desktop
806bdd1243dSDimitry Andric     case 0x8e:              // Kaby Lake mobile
807bdd1243dSDimitry Andric     case 0x9e:              // Kaby Lake desktop
808bdd1243dSDimitry Andric     case 0xa5:              // Comet Lake-H/S
809bdd1243dSDimitry Andric     case 0xa6:              // Comet Lake-U
810bdd1243dSDimitry Andric       CPU = "skylake";
811bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
812bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SKYLAKE;
813bdd1243dSDimitry Andric       break;
814bdd1243dSDimitry Andric 
815bdd1243dSDimitry Andric     // Rocketlake:
816bdd1243dSDimitry Andric     case 0xa7:
817bdd1243dSDimitry Andric       CPU = "rocketlake";
818bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
819bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ROCKETLAKE;
820bdd1243dSDimitry Andric       break;
821bdd1243dSDimitry Andric 
822bdd1243dSDimitry Andric     // Skylake Xeon:
823bdd1243dSDimitry Andric     case 0x55:
824bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
825bdd1243dSDimitry Andric       if (testFeature(X86::FEATURE_AVX512BF16)) {
826bdd1243dSDimitry Andric         CPU = "cooperlake";
827bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_COOPERLAKE;
828bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
829bdd1243dSDimitry Andric         CPU = "cascadelake";
830bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_CASCADELAKE;
831bdd1243dSDimitry Andric       } else {
832bdd1243dSDimitry Andric         CPU = "skylake-avx512";
833bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
834bdd1243dSDimitry Andric       }
835bdd1243dSDimitry Andric       break;
836bdd1243dSDimitry Andric 
837bdd1243dSDimitry Andric     // Cannonlake:
838bdd1243dSDimitry Andric     case 0x66:
839bdd1243dSDimitry Andric       CPU = "cannonlake";
840bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
841bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_CANNONLAKE;
842bdd1243dSDimitry Andric       break;
843bdd1243dSDimitry Andric 
844bdd1243dSDimitry Andric     // Icelake:
845bdd1243dSDimitry Andric     case 0x7d:
846bdd1243dSDimitry Andric     case 0x7e:
847bdd1243dSDimitry Andric       CPU = "icelake-client";
848bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
849bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
850bdd1243dSDimitry Andric       break;
851bdd1243dSDimitry Andric 
852bdd1243dSDimitry Andric     // Tigerlake:
853bdd1243dSDimitry Andric     case 0x8c:
854bdd1243dSDimitry Andric     case 0x8d:
855bdd1243dSDimitry Andric       CPU = "tigerlake";
856bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
857bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_TIGERLAKE;
858bdd1243dSDimitry Andric       break;
859bdd1243dSDimitry Andric 
860bdd1243dSDimitry Andric     // Alderlake:
861bdd1243dSDimitry Andric     case 0x97:
862bdd1243dSDimitry Andric     case 0x9a:
8635f757f3fSDimitry Andric     // Gracemont
8645f757f3fSDimitry Andric     case 0xbe:
865bdd1243dSDimitry Andric     // Raptorlake:
866bdd1243dSDimitry Andric     case 0xb7:
8675f757f3fSDimitry Andric     case 0xba:
8685f757f3fSDimitry Andric     case 0xbf:
869bdd1243dSDimitry Andric     // Meteorlake:
870bdd1243dSDimitry Andric     case 0xaa:
871bdd1243dSDimitry Andric     case 0xac:
872bdd1243dSDimitry Andric       CPU = "alderlake";
873bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
874bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
875bdd1243dSDimitry Andric       break;
876bdd1243dSDimitry Andric 
8775f757f3fSDimitry Andric     // Arrowlake:
8785f757f3fSDimitry Andric     case 0xc5:
8795f757f3fSDimitry Andric       CPU = "arrowlake";
8805f757f3fSDimitry Andric       *Type = X86::INTEL_COREI7;
8815f757f3fSDimitry Andric       *Subtype = X86::INTEL_COREI7_ARROWLAKE;
8825f757f3fSDimitry Andric       break;
8835f757f3fSDimitry Andric 
8845f757f3fSDimitry Andric     // Arrowlake S:
8855f757f3fSDimitry Andric     case 0xc6:
8865f757f3fSDimitry Andric     // Lunarlake:
8875f757f3fSDimitry Andric     case 0xbd:
8885f757f3fSDimitry Andric       CPU = "arrowlake-s";
8895f757f3fSDimitry Andric       *Type = X86::INTEL_COREI7;
8905f757f3fSDimitry Andric       *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;
8915f757f3fSDimitry Andric       break;
8925f757f3fSDimitry Andric 
8935f757f3fSDimitry Andric     // Pantherlake:
8945f757f3fSDimitry Andric     case 0xcc:
8955f757f3fSDimitry Andric       CPU = "pantherlake";
8965f757f3fSDimitry Andric       *Type = X86::INTEL_COREI7;
8975f757f3fSDimitry Andric       *Subtype = X86::INTEL_COREI7_PANTHERLAKE;
8985f757f3fSDimitry Andric       break;
8995f757f3fSDimitry Andric 
900bdd1243dSDimitry Andric     // Graniterapids:
901bdd1243dSDimitry Andric     case 0xad:
902bdd1243dSDimitry Andric       CPU = "graniterapids";
903bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
904bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS;
905bdd1243dSDimitry Andric       break;
906bdd1243dSDimitry Andric 
90706c3fb27SDimitry Andric     // Granite Rapids D:
90806c3fb27SDimitry Andric     case 0xae:
90906c3fb27SDimitry Andric       CPU = "graniterapids-d";
91006c3fb27SDimitry Andric       *Type = X86::INTEL_COREI7;
91106c3fb27SDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;
91206c3fb27SDimitry Andric       break;
91306c3fb27SDimitry Andric 
914bdd1243dSDimitry Andric     // Icelake Xeon:
915bdd1243dSDimitry Andric     case 0x6a:
916bdd1243dSDimitry Andric     case 0x6c:
917bdd1243dSDimitry Andric       CPU = "icelake-server";
918bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
919bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;
920bdd1243dSDimitry Andric       break;
921bdd1243dSDimitry Andric 
922bdd1243dSDimitry Andric     // Emerald Rapids:
923bdd1243dSDimitry Andric     case 0xcf:
924bdd1243dSDimitry Andric     // Sapphire Rapids:
925bdd1243dSDimitry Andric     case 0x8f:
926bdd1243dSDimitry Andric       CPU = "sapphirerapids";
927bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
928bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;
929bdd1243dSDimitry Andric       break;
930bdd1243dSDimitry Andric 
931bdd1243dSDimitry Andric     case 0x1c: // Most 45 nm Intel Atom processors
932bdd1243dSDimitry Andric     case 0x26: // 45 nm Atom Lincroft
933bdd1243dSDimitry Andric     case 0x27: // 32 nm Atom Medfield
934bdd1243dSDimitry Andric     case 0x35: // 32 nm Atom Midview
935bdd1243dSDimitry Andric     case 0x36: // 32 nm Atom Midview
936bdd1243dSDimitry Andric       CPU = "bonnell";
937bdd1243dSDimitry Andric       *Type = X86::INTEL_BONNELL;
938bdd1243dSDimitry Andric       break;
939bdd1243dSDimitry Andric 
940bdd1243dSDimitry Andric     // Atom Silvermont codes from the Intel software optimization guide.
941bdd1243dSDimitry Andric     case 0x37:
942bdd1243dSDimitry Andric     case 0x4a:
943bdd1243dSDimitry Andric     case 0x4d:
944bdd1243dSDimitry Andric     case 0x5a:
945bdd1243dSDimitry Andric     case 0x5d:
946bdd1243dSDimitry Andric     case 0x4c: // really airmont
947bdd1243dSDimitry Andric       CPU = "silvermont";
948bdd1243dSDimitry Andric       *Type = X86::INTEL_SILVERMONT;
949bdd1243dSDimitry Andric       break;
950bdd1243dSDimitry Andric     // Goldmont:
951bdd1243dSDimitry Andric     case 0x5c: // Apollo Lake
952bdd1243dSDimitry Andric     case 0x5f: // Denverton
953bdd1243dSDimitry Andric       CPU = "goldmont";
954bdd1243dSDimitry Andric       *Type = X86::INTEL_GOLDMONT;
955bdd1243dSDimitry Andric       break;
956bdd1243dSDimitry Andric     case 0x7a:
957bdd1243dSDimitry Andric       CPU = "goldmont-plus";
958bdd1243dSDimitry Andric       *Type = X86::INTEL_GOLDMONT_PLUS;
959bdd1243dSDimitry Andric       break;
960bdd1243dSDimitry Andric     case 0x86:
9615f757f3fSDimitry Andric     case 0x8a: // Lakefield
9625f757f3fSDimitry Andric     case 0x96: // Elkhart Lake
9635f757f3fSDimitry Andric     case 0x9c: // Jasper Lake
964bdd1243dSDimitry Andric       CPU = "tremont";
965bdd1243dSDimitry Andric       *Type = X86::INTEL_TREMONT;
966bdd1243dSDimitry Andric       break;
967bdd1243dSDimitry Andric 
968bdd1243dSDimitry Andric     // Sierraforest:
969bdd1243dSDimitry Andric     case 0xaf:
970bdd1243dSDimitry Andric       CPU = "sierraforest";
971bdd1243dSDimitry Andric       *Type = X86::INTEL_SIERRAFOREST;
972bdd1243dSDimitry Andric       break;
973bdd1243dSDimitry Andric 
974bdd1243dSDimitry Andric     // Grandridge:
975bdd1243dSDimitry Andric     case 0xb6:
976bdd1243dSDimitry Andric       CPU = "grandridge";
977bdd1243dSDimitry Andric       *Type = X86::INTEL_GRANDRIDGE;
978bdd1243dSDimitry Andric       break;
979bdd1243dSDimitry Andric 
9805f757f3fSDimitry Andric     // Clearwaterforest:
9815f757f3fSDimitry Andric     case 0xdd:
9825f757f3fSDimitry Andric       CPU = "clearwaterforest";
9835f757f3fSDimitry Andric       *Type = X86::INTEL_CLEARWATERFOREST;
9845f757f3fSDimitry Andric       break;
9855f757f3fSDimitry Andric 
986bdd1243dSDimitry Andric     // Xeon Phi (Knights Landing + Knights Mill):
987bdd1243dSDimitry Andric     case 0x57:
988bdd1243dSDimitry Andric       CPU = "knl";
989bdd1243dSDimitry Andric       *Type = X86::INTEL_KNL;
990bdd1243dSDimitry Andric       break;
991bdd1243dSDimitry Andric     case 0x85:
992bdd1243dSDimitry Andric       CPU = "knm";
993bdd1243dSDimitry Andric       *Type = X86::INTEL_KNM;
994bdd1243dSDimitry Andric       break;
995bdd1243dSDimitry Andric 
996bdd1243dSDimitry Andric     default: // Unknown family 6 CPU, try to guess.
997bdd1243dSDimitry Andric       // Don't both with Type/Subtype here, they aren't used by the caller.
998bdd1243dSDimitry Andric       // They're used above to keep the code in sync with compiler-rt.
999bdd1243dSDimitry Andric       // TODO detect tigerlake host from model
1000bdd1243dSDimitry Andric       if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {
1001bdd1243dSDimitry Andric         CPU = "tigerlake";
1002bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI2)) {
1003bdd1243dSDimitry Andric         CPU = "icelake-client";
1004bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI)) {
1005bdd1243dSDimitry Andric         CPU = "cannonlake";
1006bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512BF16)) {
1007bdd1243dSDimitry Andric         CPU = "cooperlake";
1008bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
1009bdd1243dSDimitry Andric         CPU = "cascadelake";
1010bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VL)) {
1011bdd1243dSDimitry Andric         CPU = "skylake-avx512";
1012bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {
1013bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_SHA))
1014bdd1243dSDimitry Andric           CPU = "goldmont";
1015bdd1243dSDimitry Andric         else
1016bdd1243dSDimitry Andric           CPU = "skylake";
1017bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_ADX)) {
1018bdd1243dSDimitry Andric         CPU = "broadwell";
1019bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX2)) {
1020bdd1243dSDimitry Andric         CPU = "haswell";
1021bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX)) {
1022bdd1243dSDimitry Andric         CPU = "sandybridge";
1023bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_2)) {
1024bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
1025bdd1243dSDimitry Andric           CPU = "silvermont";
1026bdd1243dSDimitry Andric         else
1027bdd1243dSDimitry Andric           CPU = "nehalem";
1028bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_1)) {
1029bdd1243dSDimitry Andric         CPU = "penryn";
1030bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSSE3)) {
1031bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
1032bdd1243dSDimitry Andric           CPU = "bonnell";
1033bdd1243dSDimitry Andric         else
1034bdd1243dSDimitry Andric           CPU = "core2";
1035bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_64BIT)) {
1036bdd1243dSDimitry Andric         CPU = "core2";
1037bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE3)) {
1038bdd1243dSDimitry Andric         CPU = "yonah";
1039bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE2)) {
1040bdd1243dSDimitry Andric         CPU = "pentium-m";
1041bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE)) {
1042bdd1243dSDimitry Andric         CPU = "pentium3";
1043bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_MMX)) {
1044bdd1243dSDimitry Andric         CPU = "pentium2";
1045bdd1243dSDimitry Andric       } else {
1046bdd1243dSDimitry Andric         CPU = "pentiumpro";
1047bdd1243dSDimitry Andric       }
1048bdd1243dSDimitry Andric       break;
1049bdd1243dSDimitry Andric     }
1050bdd1243dSDimitry Andric     break;
1051bdd1243dSDimitry Andric   case 15: {
1052bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_64BIT)) {
1053bdd1243dSDimitry Andric       CPU = "nocona";
1054bdd1243dSDimitry Andric       break;
1055bdd1243dSDimitry Andric     }
1056bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
1057bdd1243dSDimitry Andric       CPU = "prescott";
1058bdd1243dSDimitry Andric       break;
1059bdd1243dSDimitry Andric     }
1060bdd1243dSDimitry Andric     CPU = "pentium4";
1061bdd1243dSDimitry Andric     break;
1062bdd1243dSDimitry Andric   }
1063bdd1243dSDimitry Andric   default:
1064bdd1243dSDimitry Andric     break; // Unknown.
1065bdd1243dSDimitry Andric   }
1066bdd1243dSDimitry Andric 
1067bdd1243dSDimitry Andric   return CPU;
1068bdd1243dSDimitry Andric }
1069bdd1243dSDimitry Andric 
10700fca6ea1SDimitry Andric static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
10710fca6ea1SDimitry Andric                                                  unsigned Model,
1072bdd1243dSDimitry Andric                                                  const unsigned *Features,
10730fca6ea1SDimitry Andric                                                  unsigned *Type,
10740fca6ea1SDimitry Andric                                                  unsigned *Subtype) {
10750fca6ea1SDimitry Andric   const char *CPU = 0;
1076bdd1243dSDimitry Andric 
1077bdd1243dSDimitry Andric   switch (Family) {
1078bdd1243dSDimitry Andric   case 4:
1079bdd1243dSDimitry Andric     CPU = "i486";
1080bdd1243dSDimitry Andric     break;
1081bdd1243dSDimitry Andric   case 5:
1082bdd1243dSDimitry Andric     CPU = "pentium";
1083bdd1243dSDimitry Andric     switch (Model) {
1084bdd1243dSDimitry Andric     case 6:
1085bdd1243dSDimitry Andric     case 7:
1086bdd1243dSDimitry Andric       CPU = "k6";
1087bdd1243dSDimitry Andric       break;
1088bdd1243dSDimitry Andric     case 8:
1089bdd1243dSDimitry Andric       CPU = "k6-2";
1090bdd1243dSDimitry Andric       break;
1091bdd1243dSDimitry Andric     case 9:
1092bdd1243dSDimitry Andric     case 13:
1093bdd1243dSDimitry Andric       CPU = "k6-3";
1094bdd1243dSDimitry Andric       break;
1095bdd1243dSDimitry Andric     case 10:
1096bdd1243dSDimitry Andric       CPU = "geode";
1097bdd1243dSDimitry Andric       break;
1098bdd1243dSDimitry Andric     }
1099bdd1243dSDimitry Andric     break;
1100bdd1243dSDimitry Andric   case 6:
1101bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE)) {
1102bdd1243dSDimitry Andric       CPU = "athlon-xp";
1103bdd1243dSDimitry Andric       break;
1104bdd1243dSDimitry Andric     }
1105bdd1243dSDimitry Andric     CPU = "athlon";
1106bdd1243dSDimitry Andric     break;
1107bdd1243dSDimitry Andric   case 15:
1108bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
1109bdd1243dSDimitry Andric       CPU = "k8-sse3";
1110bdd1243dSDimitry Andric       break;
1111bdd1243dSDimitry Andric     }
1112bdd1243dSDimitry Andric     CPU = "k8";
1113bdd1243dSDimitry Andric     break;
1114bdd1243dSDimitry Andric   case 16:
1115bdd1243dSDimitry Andric     CPU = "amdfam10";
1116bdd1243dSDimitry Andric     *Type = X86::AMDFAM10H; // "amdfam10"
1117bdd1243dSDimitry Andric     switch (Model) {
1118bdd1243dSDimitry Andric     case 2:
1119bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_BARCELONA;
1120bdd1243dSDimitry Andric       break;
1121bdd1243dSDimitry Andric     case 4:
1122bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_SHANGHAI;
1123bdd1243dSDimitry Andric       break;
1124bdd1243dSDimitry Andric     case 8:
1125bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_ISTANBUL;
1126bdd1243dSDimitry Andric       break;
1127bdd1243dSDimitry Andric     }
1128bdd1243dSDimitry Andric     break;
1129bdd1243dSDimitry Andric   case 20:
1130bdd1243dSDimitry Andric     CPU = "btver1";
1131bdd1243dSDimitry Andric     *Type = X86::AMD_BTVER1;
1132bdd1243dSDimitry Andric     break;
1133bdd1243dSDimitry Andric   case 21:
1134bdd1243dSDimitry Andric     CPU = "bdver1";
1135bdd1243dSDimitry Andric     *Type = X86::AMDFAM15H;
1136bdd1243dSDimitry Andric     if (Model >= 0x60 && Model <= 0x7f) {
1137bdd1243dSDimitry Andric       CPU = "bdver4";
1138bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER4;
1139bdd1243dSDimitry Andric       break; // 60h-7Fh: Excavator
1140bdd1243dSDimitry Andric     }
1141bdd1243dSDimitry Andric     if (Model >= 0x30 && Model <= 0x3f) {
1142bdd1243dSDimitry Andric       CPU = "bdver3";
1143bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER3;
1144bdd1243dSDimitry Andric       break; // 30h-3Fh: Steamroller
1145bdd1243dSDimitry Andric     }
1146bdd1243dSDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
1147bdd1243dSDimitry Andric       CPU = "bdver2";
1148bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER2;
1149bdd1243dSDimitry Andric       break; // 02h, 10h-1Fh: Piledriver
1150bdd1243dSDimitry Andric     }
1151bdd1243dSDimitry Andric     if (Model <= 0x0f) {
1152bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER1;
1153bdd1243dSDimitry Andric       break; // 00h-0Fh: Bulldozer
1154bdd1243dSDimitry Andric     }
1155bdd1243dSDimitry Andric     break;
1156bdd1243dSDimitry Andric   case 22:
1157bdd1243dSDimitry Andric     CPU = "btver2";
1158bdd1243dSDimitry Andric     *Type = X86::AMD_BTVER2;
1159bdd1243dSDimitry Andric     break;
1160bdd1243dSDimitry Andric   case 23:
1161bdd1243dSDimitry Andric     CPU = "znver1";
1162bdd1243dSDimitry Andric     *Type = X86::AMDFAM17H;
1163cb14a3feSDimitry Andric     if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||
1164cb14a3feSDimitry Andric         (Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) ||
1165cb14a3feSDimitry Andric         (Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) ||
1166cb14a3feSDimitry Andric         (Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) ||
1167cb14a3feSDimitry Andric         (Model >= 0xa0 && Model <= 0xaf)) {
1168cb14a3feSDimitry Andric       // Family 17h Models 30h-3Fh (Starship) Zen 2
1169cb14a3feSDimitry Andric       // Family 17h Models 47h (Cardinal) Zen 2
1170cb14a3feSDimitry Andric       // Family 17h Models 60h-67h (Renoir) Zen 2
1171cb14a3feSDimitry Andric       // Family 17h Models 68h-6Fh (Lucienne) Zen 2
1172cb14a3feSDimitry Andric       // Family 17h Models 70h-7Fh (Matisse) Zen 2
1173cb14a3feSDimitry Andric       // Family 17h Models 84h-87h (ProjectX) Zen 2
1174cb14a3feSDimitry Andric       // Family 17h Models 90h-97h (VanGogh) Zen 2
1175cb14a3feSDimitry Andric       // Family 17h Models 98h-9Fh (Mero) Zen 2
1176cb14a3feSDimitry Andric       // Family 17h Models A0h-AFh (Mendocino) Zen 2
1177bdd1243dSDimitry Andric       CPU = "znver2";
1178bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER2;
1179cb14a3feSDimitry Andric       break;
1180bdd1243dSDimitry Andric     }
1181cb14a3feSDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) {
1182cb14a3feSDimitry Andric       // Family 17h Models 10h-1Fh (Raven1) Zen
1183cb14a3feSDimitry Andric       // Family 17h Models 10h-1Fh (Picasso) Zen+
1184cb14a3feSDimitry Andric       // Family 17h Models 20h-2Fh (Raven2 x86) Zen
1185bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER1;
1186cb14a3feSDimitry Andric       break;
1187bdd1243dSDimitry Andric     }
1188bdd1243dSDimitry Andric     break;
1189bdd1243dSDimitry Andric   case 25:
1190bdd1243dSDimitry Andric     CPU = "znver3";
1191bdd1243dSDimitry Andric     *Type = X86::AMDFAM19H;
1192647cbc5dSDimitry Andric     if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||
1193cb14a3feSDimitry Andric         (Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||
1194cb14a3feSDimitry Andric         (Model >= 0x50 && Model <= 0x5f)) {
1195cb14a3feSDimitry Andric       // Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3
1196cb14a3feSDimitry Andric       // Family 19h Models 20h-2Fh (Vermeer) Zen 3
1197cb14a3feSDimitry Andric       // Family 19h Models 30h-3Fh (Badami) Zen 3
1198cb14a3feSDimitry Andric       // Family 19h Models 40h-4Fh (Rembrandt) Zen 3+
1199cb14a3feSDimitry Andric       // Family 19h Models 50h-5Fh (Cezanne) Zen 3
1200bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER3;
1201bdd1243dSDimitry Andric       break;
1202bdd1243dSDimitry Andric     }
1203cb14a3feSDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) ||
1204cb14a3feSDimitry Andric         (Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) ||
1205cb14a3feSDimitry Andric         (Model >= 0xa0 && Model <= 0xaf)) {
1206cb14a3feSDimitry Andric       // Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 4
1207cb14a3feSDimitry Andric       // Family 19h Models 60h-6Fh (Raphael) Zen 4
1208cb14a3feSDimitry Andric       // Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 4
1209cb14a3feSDimitry Andric       // Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 4
1210cb14a3feSDimitry Andric       // Family 19h Models A0h-AFh (Stones-Dense) Zen 4
1211bdd1243dSDimitry Andric       CPU = "znver4";
1212bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER4;
1213bdd1243dSDimitry Andric       break; //  "znver4"
1214bdd1243dSDimitry Andric     }
12150fca6ea1SDimitry Andric     break; // family 19h
1216*c80e69b0SDimitry Andric   case 26:
1217*c80e69b0SDimitry Andric     CPU = "znver5";
1218*c80e69b0SDimitry Andric     *Type = X86::AMDFAM1AH;
1219*c80e69b0SDimitry Andric     if (Model <= 0x77) {
1220*c80e69b0SDimitry Andric       // Models 00h-0Fh (Breithorn).
1221*c80e69b0SDimitry Andric       // Models 10h-1Fh (Breithorn-Dense).
1222*c80e69b0SDimitry Andric       // Models 20h-2Fh (Strix 1).
1223*c80e69b0SDimitry Andric       // Models 30h-37h (Strix 2).
1224*c80e69b0SDimitry Andric       // Models 38h-3Fh (Strix 3).
1225*c80e69b0SDimitry Andric       // Models 40h-4Fh (Granite Ridge).
1226*c80e69b0SDimitry Andric       // Models 50h-5Fh (Weisshorn).
1227*c80e69b0SDimitry Andric       // Models 60h-6Fh (Krackan1).
1228*c80e69b0SDimitry Andric       // Models 70h-77h (Sarlak).
1229*c80e69b0SDimitry Andric       CPU = "znver5";
1230*c80e69b0SDimitry Andric       *Subtype = X86::AMDFAM1AH_ZNVER5;
1231*c80e69b0SDimitry Andric       break; //  "znver5"
1232*c80e69b0SDimitry Andric     }
1233*c80e69b0SDimitry Andric     break;
1234*c80e69b0SDimitry Andric 
1235bdd1243dSDimitry Andric   default:
1236bdd1243dSDimitry Andric     break; // Unknown AMD CPU.
1237bdd1243dSDimitry Andric   }
1238bdd1243dSDimitry Andric 
1239bdd1243dSDimitry Andric   return CPU;
1240bdd1243dSDimitry Andric }
1241bdd1243dSDimitry Andric 
12420fca6ea1SDimitry Andric #undef testFeature
12430fca6ea1SDimitry Andric 
1244bdd1243dSDimitry Andric static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
1245bdd1243dSDimitry Andric                                  unsigned *Features) {
1246bdd1243dSDimitry Andric   unsigned EAX, EBX;
1247bdd1243dSDimitry Andric 
1248bdd1243dSDimitry Andric   auto setFeature = [&](unsigned F) {
1249bdd1243dSDimitry Andric     Features[F / 32] |= 1U << (F % 32);
1250bdd1243dSDimitry Andric   };
1251bdd1243dSDimitry Andric 
1252bdd1243dSDimitry Andric   if ((EDX >> 15) & 1)
1253bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CMOV);
1254bdd1243dSDimitry Andric   if ((EDX >> 23) & 1)
1255bdd1243dSDimitry Andric     setFeature(X86::FEATURE_MMX);
1256bdd1243dSDimitry Andric   if ((EDX >> 25) & 1)
1257bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE);
1258bdd1243dSDimitry Andric   if ((EDX >> 26) & 1)
1259bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE2);
1260bdd1243dSDimitry Andric 
1261bdd1243dSDimitry Andric   if ((ECX >> 0) & 1)
1262bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE3);
1263bdd1243dSDimitry Andric   if ((ECX >> 1) & 1)
1264bdd1243dSDimitry Andric     setFeature(X86::FEATURE_PCLMUL);
1265bdd1243dSDimitry Andric   if ((ECX >> 9) & 1)
1266bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSSE3);
1267bdd1243dSDimitry Andric   if ((ECX >> 12) & 1)
1268bdd1243dSDimitry Andric     setFeature(X86::FEATURE_FMA);
1269bdd1243dSDimitry Andric   if ((ECX >> 19) & 1)
1270bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_1);
1271bdd1243dSDimitry Andric   if ((ECX >> 20) & 1) {
1272bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_2);
1273bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CRC32);
1274bdd1243dSDimitry Andric   }
1275bdd1243dSDimitry Andric   if ((ECX >> 23) & 1)
1276bdd1243dSDimitry Andric     setFeature(X86::FEATURE_POPCNT);
1277bdd1243dSDimitry Andric   if ((ECX >> 25) & 1)
1278bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AES);
1279bdd1243dSDimitry Andric 
1280bdd1243dSDimitry Andric   if ((ECX >> 22) & 1)
1281bdd1243dSDimitry Andric     setFeature(X86::FEATURE_MOVBE);
1282bdd1243dSDimitry Andric 
1283bdd1243dSDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1284bdd1243dSDimitry Andric   // indicates that the AVX registers will be saved and restored on context
1285bdd1243dSDimitry Andric   // switch, then we have full AVX support.
1286bdd1243dSDimitry Andric   const unsigned AVXBits = (1 << 27) | (1 << 28);
1287bdd1243dSDimitry Andric   bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
1288bdd1243dSDimitry Andric                 ((EAX & 0x6) == 0x6);
1289bdd1243dSDimitry Andric #if defined(__APPLE__)
1290bdd1243dSDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1291bdd1243dSDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1292bdd1243dSDimitry Andric   // set right now.
1293bdd1243dSDimitry Andric   bool HasAVX512Save = true;
1294bdd1243dSDimitry Andric #else
1295bdd1243dSDimitry Andric   // AVX512 requires additional context to be saved by the OS.
1296bdd1243dSDimitry Andric   bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
1297bdd1243dSDimitry Andric #endif
1298bdd1243dSDimitry Andric 
1299bdd1243dSDimitry Andric   if (HasAVX)
1300bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX);
1301bdd1243dSDimitry Andric 
1302bdd1243dSDimitry Andric   bool HasLeaf7 =
1303bdd1243dSDimitry Andric       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1304bdd1243dSDimitry Andric 
1305bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 3) & 1))
1306bdd1243dSDimitry Andric     setFeature(X86::FEATURE_BMI);
1307bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
1308bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX2);
1309bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 8) & 1))
1310bdd1243dSDimitry Andric     setFeature(X86::FEATURE_BMI2);
13115678d1d9SDimitry Andric   if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) {
1312bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512F);
13135678d1d9SDimitry Andric     setFeature(X86::FEATURE_EVEX512);
13145678d1d9SDimitry Andric   }
1315bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
1316bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512DQ);
1317bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 19) & 1))
1318bdd1243dSDimitry Andric     setFeature(X86::FEATURE_ADX);
1319bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
1320bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512IFMA);
1321bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 23) & 1))
1322bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CLFLUSHOPT);
1323bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
1324bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512CD);
1325bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 29) & 1))
1326bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SHA);
1327bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
1328bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BW);
1329bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
1330bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VL);
1331bdd1243dSDimitry Andric 
1332bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
1333bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI);
1334bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
1335bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI2);
1336bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 8) & 1))
1337bdd1243dSDimitry Andric     setFeature(X86::FEATURE_GFNI);
1338bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
1339bdd1243dSDimitry Andric     setFeature(X86::FEATURE_VPCLMULQDQ);
1340bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
1341bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VNNI);
1342bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
1343bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BITALG);
1344bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
1345bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
1346bdd1243dSDimitry Andric 
1347bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
1348bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX5124VNNIW);
1349bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
1350bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX5124FMAPS);
1351bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
1352bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VP2INTERSECT);
1353bdd1243dSDimitry Andric 
13548a4dda33SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
13558a4dda33SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
1356bdd1243dSDimitry Andric   bool HasLeaf7Subleaf1 =
13578a4dda33SDimitry Andric       HasLeaf7 && EAX >= 1 &&
13588a4dda33SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1359bdd1243dSDimitry Andric   if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
1360bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BF16);
1361bdd1243dSDimitry Andric 
1362bdd1243dSDimitry Andric   unsigned MaxExtLevel;
1363bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1364bdd1243dSDimitry Andric 
1365bdd1243dSDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1366bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1367bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 6) & 1))
1368bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_A);
1369bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 11) & 1))
1370bdd1243dSDimitry Andric     setFeature(X86::FEATURE_XOP);
1371bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 16) & 1))
1372bdd1243dSDimitry Andric     setFeature(X86::FEATURE_FMA4);
1373bdd1243dSDimitry Andric 
1374bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((EDX >> 29) & 1))
1375bdd1243dSDimitry Andric     setFeature(X86::FEATURE_64BIT);
1376bdd1243dSDimitry Andric }
1377bdd1243dSDimitry Andric 
1378bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1379bdd1243dSDimitry Andric   unsigned MaxLeaf = 0;
1380bdd1243dSDimitry Andric   const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);
1381bdd1243dSDimitry Andric   if (Vendor == VendorSignatures::UNKNOWN)
1382bdd1243dSDimitry Andric     return "generic";
1383bdd1243dSDimitry Andric 
1384bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1385bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
1386bdd1243dSDimitry Andric 
1387bdd1243dSDimitry Andric   unsigned Family = 0, Model = 0;
1388bdd1243dSDimitry Andric   unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};
1389bdd1243dSDimitry Andric   detectX86FamilyModel(EAX, &Family, &Model);
1390bdd1243dSDimitry Andric   getAvailableFeatures(ECX, EDX, MaxLeaf, Features);
1391bdd1243dSDimitry Andric 
1392bdd1243dSDimitry Andric   // These aren't consumed in this file, but we try to keep some source code the
1393bdd1243dSDimitry Andric   // same or similar to compiler-rt.
1394bdd1243dSDimitry Andric   unsigned Type = 0;
1395bdd1243dSDimitry Andric   unsigned Subtype = 0;
1396bdd1243dSDimitry Andric 
1397bdd1243dSDimitry Andric   StringRef CPU;
1398bdd1243dSDimitry Andric 
1399bdd1243dSDimitry Andric   if (Vendor == VendorSignatures::GENUINE_INTEL) {
1400bdd1243dSDimitry Andric     CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,
1401bdd1243dSDimitry Andric                                           &Subtype);
1402bdd1243dSDimitry Andric   } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {
1403bdd1243dSDimitry Andric     CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,
1404bdd1243dSDimitry Andric                                         &Subtype);
1405bdd1243dSDimitry Andric   }
1406bdd1243dSDimitry Andric 
1407bdd1243dSDimitry Andric   if (!CPU.empty())
1408bdd1243dSDimitry Andric     return CPU;
1409bdd1243dSDimitry Andric 
1410bdd1243dSDimitry Andric   return "generic";
1411bdd1243dSDimitry Andric }
1412bdd1243dSDimitry Andric 
1413bdd1243dSDimitry Andric #elif defined(__APPLE__) && defined(__powerpc__)
1414bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1415bdd1243dSDimitry Andric   host_basic_info_data_t hostInfo;
1416bdd1243dSDimitry Andric   mach_msg_type_number_t infoCount;
1417bdd1243dSDimitry Andric 
1418bdd1243dSDimitry Andric   infoCount = HOST_BASIC_INFO_COUNT;
1419bdd1243dSDimitry Andric   mach_port_t hostPort = mach_host_self();
1420bdd1243dSDimitry Andric   host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
1421bdd1243dSDimitry Andric             &infoCount);
1422bdd1243dSDimitry Andric   mach_port_deallocate(mach_task_self(), hostPort);
1423bdd1243dSDimitry Andric 
1424bdd1243dSDimitry Andric   if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
1425bdd1243dSDimitry Andric     return "generic";
1426bdd1243dSDimitry Andric 
1427bdd1243dSDimitry Andric   switch (hostInfo.cpu_subtype) {
1428bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_601:
1429bdd1243dSDimitry Andric     return "601";
1430bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_602:
1431bdd1243dSDimitry Andric     return "602";
1432bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603:
1433bdd1243dSDimitry Andric     return "603";
1434bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603e:
1435bdd1243dSDimitry Andric     return "603e";
1436bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603ev:
1437bdd1243dSDimitry Andric     return "603ev";
1438bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604:
1439bdd1243dSDimitry Andric     return "604";
1440bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604e:
1441bdd1243dSDimitry Andric     return "604e";
1442bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_620:
1443bdd1243dSDimitry Andric     return "620";
1444bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_750:
1445bdd1243dSDimitry Andric     return "750";
1446bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7400:
1447bdd1243dSDimitry Andric     return "7400";
1448bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7450:
1449bdd1243dSDimitry Andric     return "7450";
1450bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_970:
1451bdd1243dSDimitry Andric     return "970";
1452bdd1243dSDimitry Andric   default:;
1453bdd1243dSDimitry Andric   }
1454bdd1243dSDimitry Andric 
1455bdd1243dSDimitry Andric   return "generic";
1456bdd1243dSDimitry Andric }
1457bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__powerpc__)
1458bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1459bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1460bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1461bdd1243dSDimitry Andric   return detail::getHostCPUNameForPowerPC(Content);
1462bdd1243dSDimitry Andric }
1463bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1464bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1465bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1466bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1467bdd1243dSDimitry Andric   return detail::getHostCPUNameForARM(Content);
1468bdd1243dSDimitry Andric }
1469bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__s390x__)
1470bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1471bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1472bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1473bdd1243dSDimitry Andric   return detail::getHostCPUNameForS390x(Content);
1474bdd1243dSDimitry Andric }
1475bdd1243dSDimitry Andric #elif defined(__MVS__)
1476bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1477bdd1243dSDimitry Andric   // Get pointer to Communications Vector Table (CVT).
1478bdd1243dSDimitry Andric   // The pointer is located at offset 16 of the Prefixed Save Area (PSA).
1479bdd1243dSDimitry Andric   // It is stored as 31 bit pointer and will be zero-extended to 64 bit.
1480bdd1243dSDimitry Andric   int *StartToCVTOffset = reinterpret_cast<int *>(0x10);
1481bdd1243dSDimitry Andric   // Since its stored as a 31-bit pointer, get the 4 bytes from the start
1482bdd1243dSDimitry Andric   // of address.
1483bdd1243dSDimitry Andric   int ReadValue = *StartToCVTOffset;
1484bdd1243dSDimitry Andric   // Explicitly clear the high order bit.
1485bdd1243dSDimitry Andric   ReadValue = (ReadValue & 0x7FFFFFFF);
1486bdd1243dSDimitry Andric   char *CVT = reinterpret_cast<char *>(ReadValue);
1487bdd1243dSDimitry Andric   // The model number is located in the CVT prefix at offset -6 and stored as
1488bdd1243dSDimitry Andric   // signless packed decimal.
1489bdd1243dSDimitry Andric   uint16_t Id = *(uint16_t *)&CVT[-6];
1490bdd1243dSDimitry Andric   // Convert number to integer.
1491bdd1243dSDimitry Andric   Id = decodePackedBCD<uint16_t>(Id, false);
1492bdd1243dSDimitry Andric   // Check for vector support. It's stored in field CVTFLAG5 (offset 244),
1493bdd1243dSDimitry Andric   // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector
1494bdd1243dSDimitry Andric   // extension can only be used if bit CVTVEF is on.
1495bdd1243dSDimitry Andric   bool HaveVectorSupport = CVT[244] & 0x80;
1496bdd1243dSDimitry Andric   return getCPUNameFromS390Model(Id, HaveVectorSupport);
1497bdd1243dSDimitry Andric }
1498bdd1243dSDimitry Andric #elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
1499bdd1243dSDimitry Andric #define CPUFAMILY_ARM_SWIFT 0x1e2d6381
1500bdd1243dSDimitry Andric #define CPUFAMILY_ARM_CYCLONE 0x37a09642
1501bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
1502bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TWISTER 0x92fb37c8
1503bdd1243dSDimitry Andric #define CPUFAMILY_ARM_HURRICANE 0x67ceee93
1504bdd1243dSDimitry Andric #define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
1505bdd1243dSDimitry Andric #define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
1506bdd1243dSDimitry Andric #define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
1507bdd1243dSDimitry Andric #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
15080fca6ea1SDimitry Andric #define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d
15090fca6ea1SDimitry Andric #define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
1510bdd1243dSDimitry Andric 
1511bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1512bdd1243dSDimitry Andric   uint32_t Family;
1513bdd1243dSDimitry Andric   size_t Length = sizeof(Family);
1514bdd1243dSDimitry Andric   sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);
1515bdd1243dSDimitry Andric 
1516bdd1243dSDimitry Andric   switch (Family) {
1517bdd1243dSDimitry Andric   case CPUFAMILY_ARM_SWIFT:
1518bdd1243dSDimitry Andric     return "swift";
1519bdd1243dSDimitry Andric   case CPUFAMILY_ARM_CYCLONE:
1520bdd1243dSDimitry Andric     return "apple-a7";
1521bdd1243dSDimitry Andric   case CPUFAMILY_ARM_TYPHOON:
1522bdd1243dSDimitry Andric     return "apple-a8";
1523bdd1243dSDimitry Andric   case CPUFAMILY_ARM_TWISTER:
1524bdd1243dSDimitry Andric     return "apple-a9";
1525bdd1243dSDimitry Andric   case CPUFAMILY_ARM_HURRICANE:
1526bdd1243dSDimitry Andric     return "apple-a10";
1527bdd1243dSDimitry Andric   case CPUFAMILY_ARM_MONSOON_MISTRAL:
1528bdd1243dSDimitry Andric     return "apple-a11";
1529bdd1243dSDimitry Andric   case CPUFAMILY_ARM_VORTEX_TEMPEST:
1530bdd1243dSDimitry Andric     return "apple-a12";
1531bdd1243dSDimitry Andric   case CPUFAMILY_ARM_LIGHTNING_THUNDER:
1532bdd1243dSDimitry Andric     return "apple-a13";
1533bdd1243dSDimitry Andric   case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
1534bdd1243dSDimitry Andric     return "apple-m1";
15350fca6ea1SDimitry Andric   case CPUFAMILY_ARM_BLIZZARD_AVALANCHE:
15360fca6ea1SDimitry Andric     return "apple-m2";
15370fca6ea1SDimitry Andric   case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
15380fca6ea1SDimitry Andric     return "apple-m3";
1539bdd1243dSDimitry Andric   default:
1540bdd1243dSDimitry Andric     // Default to the newest CPU we know about.
15410fca6ea1SDimitry Andric     return "apple-m3";
1542bdd1243dSDimitry Andric   }
1543bdd1243dSDimitry Andric }
1544bdd1243dSDimitry Andric #elif defined(_AIX)
1545bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1546bdd1243dSDimitry Andric   switch (_system_configuration.implementation) {
1547bdd1243dSDimitry Andric   case POWER_4:
1548bdd1243dSDimitry Andric     if (_system_configuration.version == PV_4_3)
1549bdd1243dSDimitry Andric       return "970";
1550bdd1243dSDimitry Andric     return "pwr4";
1551bdd1243dSDimitry Andric   case POWER_5:
1552bdd1243dSDimitry Andric     if (_system_configuration.version == PV_5)
1553bdd1243dSDimitry Andric       return "pwr5";
1554bdd1243dSDimitry Andric     return "pwr5x";
1555bdd1243dSDimitry Andric   case POWER_6:
1556bdd1243dSDimitry Andric     if (_system_configuration.version == PV_6_Compat)
1557bdd1243dSDimitry Andric       return "pwr6";
1558bdd1243dSDimitry Andric     return "pwr6x";
1559bdd1243dSDimitry Andric   case POWER_7:
1560bdd1243dSDimitry Andric     return "pwr7";
1561bdd1243dSDimitry Andric   case POWER_8:
1562bdd1243dSDimitry Andric     return "pwr8";
1563bdd1243dSDimitry Andric   case POWER_9:
1564bdd1243dSDimitry Andric     return "pwr9";
1565bdd1243dSDimitry Andric // TODO: simplify this once the macro is available in all OS levels.
1566bdd1243dSDimitry Andric #ifdef POWER_10
1567bdd1243dSDimitry Andric   case POWER_10:
1568bdd1243dSDimitry Andric #else
1569bdd1243dSDimitry Andric   case 0x40000:
1570bdd1243dSDimitry Andric #endif
1571bdd1243dSDimitry Andric     return "pwr10";
157236b606aeSDimitry Andric #ifdef POWER_11
157336b606aeSDimitry Andric   case POWER_11:
157436b606aeSDimitry Andric #else
157536b606aeSDimitry Andric   case 0x80000:
157636b606aeSDimitry Andric #endif
157736b606aeSDimitry Andric     return "pwr11";
1578bdd1243dSDimitry Andric   default:
1579bdd1243dSDimitry Andric     return "generic";
1580bdd1243dSDimitry Andric   }
1581bdd1243dSDimitry Andric }
158206c3fb27SDimitry Andric #elif defined(__loongarch__)
158306c3fb27SDimitry Andric StringRef sys::getHostCPUName() {
158406c3fb27SDimitry Andric   // Use processor id to detect cpu name.
158506c3fb27SDimitry Andric   uint32_t processor_id;
158606c3fb27SDimitry Andric   __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));
15871db9f3b2SDimitry Andric   // Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h.
15881db9f3b2SDimitry Andric   switch (processor_id & 0xf000) {
158906c3fb27SDimitry Andric   case 0xc000: // Loongson 64bit, 4-issue
159006c3fb27SDimitry Andric     return "la464";
15910fca6ea1SDimitry Andric   case 0xd000: // Loongson 64bit, 6-issue
15920fca6ea1SDimitry Andric     return "la664";
159306c3fb27SDimitry Andric   // TODO: Others.
159406c3fb27SDimitry Andric   default:
159506c3fb27SDimitry Andric     break;
159606c3fb27SDimitry Andric   }
159706c3fb27SDimitry Andric   return "generic";
159806c3fb27SDimitry Andric }
1599bdd1243dSDimitry Andric #elif defined(__riscv)
1600bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1601bdd1243dSDimitry Andric #if defined(__linux__)
1602bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1603bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
16040fca6ea1SDimitry Andric   StringRef Name = detail::getHostCPUNameForRISCV(Content);
16050fca6ea1SDimitry Andric   if (!Name.empty())
16060fca6ea1SDimitry Andric     return Name;
16070fca6ea1SDimitry Andric #endif
1608bdd1243dSDimitry Andric #if __riscv_xlen == 64
1609bdd1243dSDimitry Andric   return "generic-rv64";
1610bdd1243dSDimitry Andric #elif __riscv_xlen == 32
1611bdd1243dSDimitry Andric   return "generic-rv32";
1612bdd1243dSDimitry Andric #else
1613bdd1243dSDimitry Andric #error "Unhandled value of __riscv_xlen"
1614bdd1243dSDimitry Andric #endif
1615bdd1243dSDimitry Andric }
1616bdd1243dSDimitry Andric #elif defined(__sparc__)
1617bdd1243dSDimitry Andric #if defined(__linux__)
1618bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {
1619bdd1243dSDimitry Andric   SmallVector<StringRef> Lines;
1620bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
1621bdd1243dSDimitry Andric 
1622bdd1243dSDimitry Andric   // Look for cpu line to determine cpu name
1623bdd1243dSDimitry Andric   StringRef Cpu;
1624bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
16255f757f3fSDimitry Andric     if (Lines[I].starts_with("cpu")) {
1626bdd1243dSDimitry Andric       Cpu = Lines[I].substr(5).ltrim("\t :");
1627bdd1243dSDimitry Andric       break;
1628bdd1243dSDimitry Andric     }
1629bdd1243dSDimitry Andric   }
1630bdd1243dSDimitry Andric 
1631bdd1243dSDimitry Andric   return StringSwitch<const char *>(Cpu)
1632bdd1243dSDimitry Andric       .StartsWith("SuperSparc", "supersparc")
1633bdd1243dSDimitry Andric       .StartsWith("HyperSparc", "hypersparc")
1634bdd1243dSDimitry Andric       .StartsWith("SpitFire", "ultrasparc")
1635bdd1243dSDimitry Andric       .StartsWith("BlackBird", "ultrasparc")
1636bdd1243dSDimitry Andric       .StartsWith("Sabre", " ultrasparc")
1637bdd1243dSDimitry Andric       .StartsWith("Hummingbird", "ultrasparc")
1638bdd1243dSDimitry Andric       .StartsWith("Cheetah", "ultrasparc3")
1639bdd1243dSDimitry Andric       .StartsWith("Jalapeno", "ultrasparc3")
1640bdd1243dSDimitry Andric       .StartsWith("Jaguar", "ultrasparc3")
1641bdd1243dSDimitry Andric       .StartsWith("Panther", "ultrasparc3")
1642bdd1243dSDimitry Andric       .StartsWith("Serrano", "ultrasparc3")
1643bdd1243dSDimitry Andric       .StartsWith("UltraSparc T1", "niagara")
1644bdd1243dSDimitry Andric       .StartsWith("UltraSparc T2", "niagara2")
1645bdd1243dSDimitry Andric       .StartsWith("UltraSparc T3", "niagara3")
1646bdd1243dSDimitry Andric       .StartsWith("UltraSparc T4", "niagara4")
1647bdd1243dSDimitry Andric       .StartsWith("UltraSparc T5", "niagara4")
1648bdd1243dSDimitry Andric       .StartsWith("LEON", "leon3")
1649bdd1243dSDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1650bdd1243dSDimitry Andric       .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)
1651bdd1243dSDimitry Andric       .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)
1652bdd1243dSDimitry Andric       .StartsWith("SPARC-M8", "niagara4" /* "m8" */)
1653bdd1243dSDimitry Andric       .Default("generic");
1654bdd1243dSDimitry Andric }
1655bdd1243dSDimitry Andric #endif
1656bdd1243dSDimitry Andric 
1657bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1658bdd1243dSDimitry Andric #if defined(__linux__)
1659bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1660bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1661bdd1243dSDimitry Andric   return detail::getHostCPUNameForSPARC(Content);
1662bdd1243dSDimitry Andric #elif defined(__sun__) && defined(__svr4__)
1663bdd1243dSDimitry Andric   char *buf = NULL;
1664bdd1243dSDimitry Andric   kstat_ctl_t *kc;
1665bdd1243dSDimitry Andric   kstat_t *ksp;
1666bdd1243dSDimitry Andric   kstat_named_t *brand = NULL;
1667bdd1243dSDimitry Andric 
1668bdd1243dSDimitry Andric   kc = kstat_open();
1669bdd1243dSDimitry Andric   if (kc != NULL) {
1670bdd1243dSDimitry Andric     ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);
1671bdd1243dSDimitry Andric     if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&
1672bdd1243dSDimitry Andric         ksp->ks_type == KSTAT_TYPE_NAMED)
1673bdd1243dSDimitry Andric       brand =
1674bdd1243dSDimitry Andric           (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));
1675bdd1243dSDimitry Andric     if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
1676bdd1243dSDimitry Andric       buf = KSTAT_NAMED_STR_PTR(brand);
1677bdd1243dSDimitry Andric   }
1678bdd1243dSDimitry Andric   kstat_close(kc);
1679bdd1243dSDimitry Andric 
1680bdd1243dSDimitry Andric   return StringSwitch<const char *>(buf)
1681bdd1243dSDimitry Andric       .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I
1682bdd1243dSDimitry Andric       .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I
1683bdd1243dSDimitry Andric       .Case("TMS390Z55",
1684bdd1243dSDimitry Andric             "supersparc") // Texas Instruments SuperSPARC I with SuperCache
1685bdd1243dSDimitry Andric       .Case("MB86904", "supersparc") // Fujitsu microSPARC II
1686bdd1243dSDimitry Andric       .Case("MB86907", "supersparc") // Fujitsu TurboSPARC
1687bdd1243dSDimitry Andric       .Case("RT623", "hypersparc")   // Ross hyperSPARC
1688bdd1243dSDimitry Andric       .Case("RT625", "hypersparc")
1689bdd1243dSDimitry Andric       .Case("RT626", "hypersparc")
1690bdd1243dSDimitry Andric       .Case("UltraSPARC-I", "ultrasparc")
1691bdd1243dSDimitry Andric       .Case("UltraSPARC-II", "ultrasparc")
1692bdd1243dSDimitry Andric       .Case("UltraSPARC-IIe", "ultrasparc")
1693bdd1243dSDimitry Andric       .Case("UltraSPARC-IIi", "ultrasparc")
1694bdd1243dSDimitry Andric       .Case("SPARC64-III", "ultrasparc")
1695bdd1243dSDimitry Andric       .Case("SPARC64-IV", "ultrasparc")
1696bdd1243dSDimitry Andric       .Case("UltraSPARC-III", "ultrasparc3")
1697bdd1243dSDimitry Andric       .Case("UltraSPARC-III+", "ultrasparc3")
1698bdd1243dSDimitry Andric       .Case("UltraSPARC-IIIi", "ultrasparc3")
1699bdd1243dSDimitry Andric       .Case("UltraSPARC-IIIi+", "ultrasparc3")
1700bdd1243dSDimitry Andric       .Case("UltraSPARC-IV", "ultrasparc3")
1701bdd1243dSDimitry Andric       .Case("UltraSPARC-IV+", "ultrasparc3")
1702bdd1243dSDimitry Andric       .Case("SPARC64-V", "ultrasparc3")
1703bdd1243dSDimitry Andric       .Case("SPARC64-VI", "ultrasparc3")
1704bdd1243dSDimitry Andric       .Case("SPARC64-VII", "ultrasparc3")
1705bdd1243dSDimitry Andric       .Case("UltraSPARC-T1", "niagara")
1706bdd1243dSDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1707bdd1243dSDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1708bdd1243dSDimitry Andric       .Case("UltraSPARC-T2+", "niagara2")
1709bdd1243dSDimitry Andric       .Case("SPARC-T3", "niagara3")
1710bdd1243dSDimitry Andric       .Case("SPARC-T4", "niagara4")
1711bdd1243dSDimitry Andric       .Case("SPARC-T5", "niagara4")
1712bdd1243dSDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1713bdd1243dSDimitry Andric       .Case("SPARC-M7", "niagara4" /* "niagara7" */)
1714bdd1243dSDimitry Andric       .Case("SPARC-S7", "niagara4" /* "niagara7" */)
1715bdd1243dSDimitry Andric       .Case("SPARC-M8", "niagara4" /* "m8" */)
1716bdd1243dSDimitry Andric       .Default("generic");
1717bdd1243dSDimitry Andric #else
1718bdd1243dSDimitry Andric   return "generic";
1719bdd1243dSDimitry Andric #endif
1720bdd1243dSDimitry Andric }
1721bdd1243dSDimitry Andric #else
1722bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { return "generic"; }
1723bdd1243dSDimitry Andric namespace llvm {
1724bdd1243dSDimitry Andric namespace sys {
1725bdd1243dSDimitry Andric namespace detail {
1726bdd1243dSDimitry Andric namespace x86 {
1727bdd1243dSDimitry Andric 
1728bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
1729bdd1243dSDimitry Andric   return VendorSignatures::UNKNOWN;
1730bdd1243dSDimitry Andric }
1731bdd1243dSDimitry Andric 
1732bdd1243dSDimitry Andric } // namespace x86
1733bdd1243dSDimitry Andric } // namespace detail
1734bdd1243dSDimitry Andric } // namespace sys
1735bdd1243dSDimitry Andric } // namespace llvm
1736bdd1243dSDimitry Andric #endif
1737bdd1243dSDimitry Andric 
1738bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
1739bdd1243dSDimitry Andric     defined(__x86_64__) || defined(_M_X64)
17400fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
1741bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1742bdd1243dSDimitry Andric   unsigned MaxLevel;
17430fca6ea1SDimitry Andric   StringMap<bool> Features;
1744bdd1243dSDimitry Andric 
1745bdd1243dSDimitry Andric   if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)
17460fca6ea1SDimitry Andric     return Features;
1747bdd1243dSDimitry Andric 
1748bdd1243dSDimitry Andric   getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1749bdd1243dSDimitry Andric 
1750bdd1243dSDimitry Andric   Features["cx8"]    = (EDX >>  8) & 1;
1751bdd1243dSDimitry Andric   Features["cmov"]   = (EDX >> 15) & 1;
1752bdd1243dSDimitry Andric   Features["mmx"]    = (EDX >> 23) & 1;
1753bdd1243dSDimitry Andric   Features["fxsr"]   = (EDX >> 24) & 1;
1754bdd1243dSDimitry Andric   Features["sse"]    = (EDX >> 25) & 1;
1755bdd1243dSDimitry Andric   Features["sse2"]   = (EDX >> 26) & 1;
1756bdd1243dSDimitry Andric 
1757bdd1243dSDimitry Andric   Features["sse3"]   = (ECX >>  0) & 1;
1758bdd1243dSDimitry Andric   Features["pclmul"] = (ECX >>  1) & 1;
1759bdd1243dSDimitry Andric   Features["ssse3"]  = (ECX >>  9) & 1;
1760bdd1243dSDimitry Andric   Features["cx16"]   = (ECX >> 13) & 1;
1761bdd1243dSDimitry Andric   Features["sse4.1"] = (ECX >> 19) & 1;
1762bdd1243dSDimitry Andric   Features["sse4.2"] = (ECX >> 20) & 1;
1763bdd1243dSDimitry Andric   Features["crc32"]  = Features["sse4.2"];
1764bdd1243dSDimitry Andric   Features["movbe"]  = (ECX >> 22) & 1;
1765bdd1243dSDimitry Andric   Features["popcnt"] = (ECX >> 23) & 1;
1766bdd1243dSDimitry Andric   Features["aes"]    = (ECX >> 25) & 1;
1767bdd1243dSDimitry Andric   Features["rdrnd"]  = (ECX >> 30) & 1;
1768bdd1243dSDimitry Andric 
1769bdd1243dSDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1770bdd1243dSDimitry Andric   // indicates that the AVX registers will be saved and restored on context
1771bdd1243dSDimitry Andric   // switch, then we have full AVX support.
1772bdd1243dSDimitry Andric   bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
1773bdd1243dSDimitry Andric   bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);
1774bdd1243dSDimitry Andric #if defined(__APPLE__)
1775bdd1243dSDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1776bdd1243dSDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1777bdd1243dSDimitry Andric   // set right now.
1778bdd1243dSDimitry Andric   bool HasAVX512Save = true;
1779bdd1243dSDimitry Andric #else
1780bdd1243dSDimitry Andric   // AVX512 requires additional context to be saved by the OS.
1781bdd1243dSDimitry Andric   bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1782bdd1243dSDimitry Andric #endif
1783bdd1243dSDimitry Andric   // AMX requires additional context to be saved by the OS.
1784bdd1243dSDimitry Andric   const unsigned AMXBits = (1 << 17) | (1 << 18);
1785bdd1243dSDimitry Andric   bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
1786bdd1243dSDimitry Andric 
1787bdd1243dSDimitry Andric   Features["avx"]   = HasAVXSave;
1788bdd1243dSDimitry Andric   Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;
1789bdd1243dSDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1790bdd1243dSDimitry Andric   Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1791bdd1243dSDimitry Andric   Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;
1792bdd1243dSDimitry Andric 
1793bdd1243dSDimitry Andric   unsigned MaxExtLevel;
1794bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1795bdd1243dSDimitry Andric 
1796bdd1243dSDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1797bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1798bdd1243dSDimitry Andric   Features["sahf"]   = HasExtLeaf1 && ((ECX >>  0) & 1);
1799bdd1243dSDimitry Andric   Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);
1800bdd1243dSDimitry Andric   Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);
1801bdd1243dSDimitry Andric   Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);
1802bdd1243dSDimitry Andric   Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1803bdd1243dSDimitry Andric   Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);
1804bdd1243dSDimitry Andric   Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1805bdd1243dSDimitry Andric   Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);
1806bdd1243dSDimitry Andric   Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1807bdd1243dSDimitry Andric 
1808bdd1243dSDimitry Andric   Features["64bit"]  = HasExtLeaf1 && ((EDX >> 29) & 1);
1809bdd1243dSDimitry Andric 
1810bdd1243dSDimitry Andric   // Miscellaneous memory related features, detected by
1811bdd1243dSDimitry Andric   // using the 0x80000008 leaf of the CPUID instruction
1812bdd1243dSDimitry Andric   bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
1813bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
1814bdd1243dSDimitry Andric   Features["clzero"]   = HasExtLeaf8 && ((EBX >> 0) & 1);
1815bdd1243dSDimitry Andric   Features["rdpru"]    = HasExtLeaf8 && ((EBX >> 4) & 1);
1816bdd1243dSDimitry Andric   Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
1817bdd1243dSDimitry Andric 
1818bdd1243dSDimitry Andric   bool HasLeaf7 =
1819bdd1243dSDimitry Andric       MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1820bdd1243dSDimitry Andric 
1821bdd1243dSDimitry Andric   Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);
1822bdd1243dSDimitry Andric   Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);
1823bdd1243dSDimitry Andric   Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);
1824bdd1243dSDimitry Andric   // AVX2 is only supported if we have the OS save support from AVX.
1825bdd1243dSDimitry Andric   Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;
1826bdd1243dSDimitry Andric   Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);
1827bdd1243dSDimitry Andric   Features["invpcid"]    = HasLeaf7 && ((EBX >> 10) & 1);
1828bdd1243dSDimitry Andric   Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);
1829bdd1243dSDimitry Andric   // AVX512 is only supported if the OS supports the context save for it.
1830bdd1243dSDimitry Andric   Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1831fcfb2d63SDimitry Andric   if (Features["avx512f"])
1832fcfb2d63SDimitry Andric     Features["evex512"]  = true;
1833bdd1243dSDimitry Andric   Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1834bdd1243dSDimitry Andric   Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);
1835bdd1243dSDimitry Andric   Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);
1836bdd1243dSDimitry Andric   Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
1837bdd1243dSDimitry Andric   Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1838bdd1243dSDimitry Andric   Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);
1839bdd1243dSDimitry Andric   Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1840bdd1243dSDimitry Andric   Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);
1841bdd1243dSDimitry Andric   Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1842bdd1243dSDimitry Andric   Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
1843bdd1243dSDimitry Andric 
1844bdd1243dSDimitry Andric   Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;
1845bdd1243dSDimitry Andric   Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);
1846bdd1243dSDimitry Andric   Features["waitpkg"]         = HasLeaf7 && ((ECX >>  5) & 1);
1847bdd1243dSDimitry Andric   Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;
1848bdd1243dSDimitry Andric   Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);
1849bdd1243dSDimitry Andric   Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);
1850bdd1243dSDimitry Andric   Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;
1851bdd1243dSDimitry Andric   Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1852bdd1243dSDimitry Andric   Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1853bdd1243dSDimitry Andric   Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
1854bdd1243dSDimitry Andric   Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
1855bdd1243dSDimitry Andric   Features["rdpid"]           = HasLeaf7 && ((ECX >> 22) & 1);
1856bdd1243dSDimitry Andric   Features["kl"]              = HasLeaf7 && ((ECX >> 23) & 1); // key locker
1857bdd1243dSDimitry Andric   Features["cldemote"]        = HasLeaf7 && ((ECX >> 25) & 1);
1858bdd1243dSDimitry Andric   Features["movdiri"]         = HasLeaf7 && ((ECX >> 27) & 1);
1859bdd1243dSDimitry Andric   Features["movdir64b"]       = HasLeaf7 && ((ECX >> 28) & 1);
1860bdd1243dSDimitry Andric   Features["enqcmd"]          = HasLeaf7 && ((ECX >> 29) & 1);
1861bdd1243dSDimitry Andric 
1862bdd1243dSDimitry Andric   Features["uintr"]           = HasLeaf7 && ((EDX >> 5) & 1);
1863bdd1243dSDimitry Andric   Features["avx512vp2intersect"] =
1864bdd1243dSDimitry Andric       HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;
1865bdd1243dSDimitry Andric   Features["serialize"]       = HasLeaf7 && ((EDX >> 14) & 1);
1866bdd1243dSDimitry Andric   Features["tsxldtrk"]        = HasLeaf7 && ((EDX >> 16) & 1);
1867bdd1243dSDimitry Andric   // There are two CPUID leafs which information associated with the pconfig
1868bdd1243dSDimitry Andric   // instruction:
1869bdd1243dSDimitry Andric   // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
1870bdd1243dSDimitry Andric   // bit of EDX), while the EAX=0x1b leaf returns information on the
1871bdd1243dSDimitry Andric   // availability of specific pconfig leafs.
1872bdd1243dSDimitry Andric   // The target feature here only refers to the the first of these two.
1873bdd1243dSDimitry Andric   // Users might need to check for the availability of specific pconfig
1874bdd1243dSDimitry Andric   // leaves using cpuid, since that information is ignored while
1875bdd1243dSDimitry Andric   // detecting features using the "-march=native" flag.
1876bdd1243dSDimitry Andric   // For more info, see X86 ISA docs.
1877bdd1243dSDimitry Andric   Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
1878bdd1243dSDimitry Andric   Features["amx-bf16"]   = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;
1879bdd1243dSDimitry Andric   Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;
1880bdd1243dSDimitry Andric   Features["amx-tile"]   = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;
1881bdd1243dSDimitry Andric   Features["amx-int8"]   = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;
18828a4dda33SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
18838a4dda33SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
1884bdd1243dSDimitry Andric   bool HasLeaf7Subleaf1 =
18858a4dda33SDimitry Andric       HasLeaf7 && EAX >= 1 &&
18868a4dda33SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
188706c3fb27SDimitry Andric   Features["sha512"]     = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);
188806c3fb27SDimitry Andric   Features["sm3"]        = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);
188906c3fb27SDimitry Andric   Features["sm4"]        = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);
1890bdd1243dSDimitry Andric   Features["raoint"]     = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);
1891bdd1243dSDimitry Andric   Features["avxvnni"]    = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;
1892bdd1243dSDimitry Andric   Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;
1893bdd1243dSDimitry Andric   Features["amx-fp16"]   = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;
1894bdd1243dSDimitry Andric   Features["cmpccxadd"]  = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);
1895bdd1243dSDimitry Andric   Features["hreset"]     = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);
1896bdd1243dSDimitry Andric   Features["avxifma"]    = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;
1897bdd1243dSDimitry Andric   Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;
1898bdd1243dSDimitry Andric   Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;
189906c3fb27SDimitry Andric   Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;
190006c3fb27SDimitry Andric   Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;
1901bdd1243dSDimitry Andric   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
19025f757f3fSDimitry Andric   Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);
19035f757f3fSDimitry Andric   Features["avx10.1-256"] = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
19040fca6ea1SDimitry Andric   bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);
19050fca6ea1SDimitry Andric   Features["egpr"] = HasAPXF;
19060fca6ea1SDimitry Andric   Features["push2pop2"] = HasAPXF;
19070fca6ea1SDimitry Andric   Features["ppx"] = HasAPXF;
19080fca6ea1SDimitry Andric   Features["ndd"] = HasAPXF;
19090fca6ea1SDimitry Andric   Features["ccmp"] = HasAPXF;
19100fca6ea1SDimitry Andric   Features["cf"] = HasAPXF;
1911bdd1243dSDimitry Andric 
1912bdd1243dSDimitry Andric   bool HasLeafD = MaxLevel >= 0xd &&
1913bdd1243dSDimitry Andric                   !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1914bdd1243dSDimitry Andric 
1915bdd1243dSDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1916bdd1243dSDimitry Andric   Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1917bdd1243dSDimitry Andric   Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1918bdd1243dSDimitry Andric   Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
1919bdd1243dSDimitry Andric 
1920bdd1243dSDimitry Andric   bool HasLeaf14 = MaxLevel >= 0x14 &&
1921bdd1243dSDimitry Andric                   !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
1922bdd1243dSDimitry Andric 
1923bdd1243dSDimitry Andric   Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
1924bdd1243dSDimitry Andric 
1925bdd1243dSDimitry Andric   bool HasLeaf19 =
1926bdd1243dSDimitry Andric       MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);
1927bdd1243dSDimitry Andric   Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);
1928bdd1243dSDimitry Andric 
19295f757f3fSDimitry Andric   bool HasLeaf24 =
19305f757f3fSDimitry Andric       MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);
19315f757f3fSDimitry Andric   Features["avx10.1-512"] =
19325f757f3fSDimitry Andric       Features["avx10.1-256"] && HasLeaf24 && ((EBX >> 18) & 1);
19335f757f3fSDimitry Andric 
19340fca6ea1SDimitry Andric   return Features;
1935bdd1243dSDimitry Andric }
1936bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
19370fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
19380fca6ea1SDimitry Andric   StringMap<bool> Features;
1939bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1940bdd1243dSDimitry Andric   if (!P)
19410fca6ea1SDimitry Andric     return Features;
1942bdd1243dSDimitry Andric 
1943bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
1944bdd1243dSDimitry Andric   P->getBuffer().split(Lines, "\n");
1945bdd1243dSDimitry Andric 
1946bdd1243dSDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
1947bdd1243dSDimitry Andric 
1948bdd1243dSDimitry Andric   // Look for the CPU features.
1949bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
19505f757f3fSDimitry Andric     if (Lines[I].starts_with("Features")) {
1951bdd1243dSDimitry Andric       Lines[I].split(CPUFeatures, ' ');
1952bdd1243dSDimitry Andric       break;
1953bdd1243dSDimitry Andric     }
1954bdd1243dSDimitry Andric 
1955bdd1243dSDimitry Andric #if defined(__aarch64__)
1956bdd1243dSDimitry Andric   // Keep track of which crypto features we have seen
1957bdd1243dSDimitry Andric   enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
1958bdd1243dSDimitry Andric   uint32_t crypto = 0;
1959bdd1243dSDimitry Andric #endif
1960bdd1243dSDimitry Andric 
1961bdd1243dSDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
1962bdd1243dSDimitry Andric     StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
1963bdd1243dSDimitry Andric #if defined(__aarch64__)
1964bdd1243dSDimitry Andric                                    .Case("asimd", "neon")
1965bdd1243dSDimitry Andric                                    .Case("fp", "fp-armv8")
1966bdd1243dSDimitry Andric                                    .Case("crc32", "crc")
1967bdd1243dSDimitry Andric                                    .Case("atomics", "lse")
1968bdd1243dSDimitry Andric                                    .Case("sve", "sve")
1969bdd1243dSDimitry Andric                                    .Case("sve2", "sve2")
1970bdd1243dSDimitry Andric #else
1971bdd1243dSDimitry Andric                                    .Case("half", "fp16")
1972bdd1243dSDimitry Andric                                    .Case("neon", "neon")
1973bdd1243dSDimitry Andric                                    .Case("vfpv3", "vfp3")
1974bdd1243dSDimitry Andric                                    .Case("vfpv3d16", "vfp3d16")
1975bdd1243dSDimitry Andric                                    .Case("vfpv4", "vfp4")
1976bdd1243dSDimitry Andric                                    .Case("idiva", "hwdiv-arm")
1977bdd1243dSDimitry Andric                                    .Case("idivt", "hwdiv")
1978bdd1243dSDimitry Andric #endif
1979bdd1243dSDimitry Andric                                    .Default("");
1980bdd1243dSDimitry Andric 
1981bdd1243dSDimitry Andric #if defined(__aarch64__)
1982bdd1243dSDimitry Andric     // We need to check crypto separately since we need all of the crypto
1983bdd1243dSDimitry Andric     // extensions to enable the subtarget feature
1984bdd1243dSDimitry Andric     if (CPUFeatures[I] == "aes")
1985bdd1243dSDimitry Andric       crypto |= CAP_AES;
1986bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "pmull")
1987bdd1243dSDimitry Andric       crypto |= CAP_PMULL;
1988bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "sha1")
1989bdd1243dSDimitry Andric       crypto |= CAP_SHA1;
1990bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "sha2")
1991bdd1243dSDimitry Andric       crypto |= CAP_SHA2;
1992bdd1243dSDimitry Andric #endif
1993bdd1243dSDimitry Andric 
1994bdd1243dSDimitry Andric     if (LLVMFeatureStr != "")
1995bdd1243dSDimitry Andric       Features[LLVMFeatureStr] = true;
1996bdd1243dSDimitry Andric   }
1997bdd1243dSDimitry Andric 
1998bdd1243dSDimitry Andric #if defined(__aarch64__)
1999bdd1243dSDimitry Andric   // If we have all crypto bits we can add the feature
2000bdd1243dSDimitry Andric   if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
2001bdd1243dSDimitry Andric     Features["crypto"] = true;
2002bdd1243dSDimitry Andric #endif
2003bdd1243dSDimitry Andric 
20040fca6ea1SDimitry Andric   return Features;
2005bdd1243dSDimitry Andric }
2006bdd1243dSDimitry Andric #elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
20070fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
20080fca6ea1SDimitry Andric   StringMap<bool> Features;
20090fca6ea1SDimitry Andric 
2010bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
2011bdd1243dSDimitry Andric     Features["neon"] = true;
2012bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
2013bdd1243dSDimitry Andric     Features["crc"] = true;
2014bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
2015bdd1243dSDimitry Andric     Features["crypto"] = true;
2016bdd1243dSDimitry Andric 
20170fca6ea1SDimitry Andric   return Features;
2018bdd1243dSDimitry Andric }
201906c3fb27SDimitry Andric #elif defined(__linux__) && defined(__loongarch__)
202006c3fb27SDimitry Andric #include <sys/auxv.h>
20210fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
202206c3fb27SDimitry Andric   unsigned long hwcap = getauxval(AT_HWCAP);
202306c3fb27SDimitry Andric   bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU
202406c3fb27SDimitry Andric   uint32_t cpucfg2 = 0x2;
202506c3fb27SDimitry Andric   __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));
202606c3fb27SDimitry Andric 
20270fca6ea1SDimitry Andric   StringMap<bool> Features;
20280fca6ea1SDimitry Andric 
202906c3fb27SDimitry Andric   Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP
203006c3fb27SDimitry Andric   Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP
203106c3fb27SDimitry Andric 
203206c3fb27SDimitry Andric   Features["lsx"] = hwcap & (1UL << 4);  // HWCAP_LOONGARCH_LSX
203306c3fb27SDimitry Andric   Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX
203406c3fb27SDimitry Andric   Features["lvz"] = hwcap & (1UL << 9);  // HWCAP_LOONGARCH_LVZ
203506c3fb27SDimitry Andric 
20360fca6ea1SDimitry Andric   return Features;
20370fca6ea1SDimitry Andric }
20380fca6ea1SDimitry Andric #elif defined(__linux__) && defined(__riscv)
20390fca6ea1SDimitry Andric // struct riscv_hwprobe
20400fca6ea1SDimitry Andric struct RISCVHwProbe {
20410fca6ea1SDimitry Andric   int64_t Key;
20420fca6ea1SDimitry Andric   uint64_t Value;
20430fca6ea1SDimitry Andric };
20440fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
20450fca6ea1SDimitry Andric   RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0},
20460fca6ea1SDimitry Andric                        {/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0}};
20470fca6ea1SDimitry Andric   int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,
20480fca6ea1SDimitry Andric                     /*pair_count=*/std::size(Query), /*cpu_count=*/0,
20490fca6ea1SDimitry Andric                     /*cpus=*/0, /*flags=*/0);
20500fca6ea1SDimitry Andric   if (Ret != 0)
20510fca6ea1SDimitry Andric     return {};
20520fca6ea1SDimitry Andric 
20530fca6ea1SDimitry Andric   StringMap<bool> Features;
20540fca6ea1SDimitry Andric   uint64_t BaseMask = Query[0].Value;
20550fca6ea1SDimitry Andric   // Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set.
20560fca6ea1SDimitry Andric   if (BaseMask & 1) {
20570fca6ea1SDimitry Andric     Features["i"] = true;
20580fca6ea1SDimitry Andric     Features["m"] = true;
20590fca6ea1SDimitry Andric     Features["a"] = true;
20600fca6ea1SDimitry Andric   }
20610fca6ea1SDimitry Andric 
20620fca6ea1SDimitry Andric   uint64_t ExtMask = Query[1].Value;
20630fca6ea1SDimitry Andric   Features["f"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
20640fca6ea1SDimitry Andric   Features["d"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
20650fca6ea1SDimitry Andric   Features["c"] = ExtMask & (1 << 1);           // RISCV_HWPROBE_IMA_C
20660fca6ea1SDimitry Andric   Features["v"] = ExtMask & (1 << 2);           // RISCV_HWPROBE_IMA_V
20670fca6ea1SDimitry Andric   Features["zba"] = ExtMask & (1 << 3);         // RISCV_HWPROBE_EXT_ZBA
20680fca6ea1SDimitry Andric   Features["zbb"] = ExtMask & (1 << 4);         // RISCV_HWPROBE_EXT_ZBB
20690fca6ea1SDimitry Andric   Features["zbs"] = ExtMask & (1 << 5);         // RISCV_HWPROBE_EXT_ZBS
20700fca6ea1SDimitry Andric   Features["zicboz"] = ExtMask & (1 << 6);      // RISCV_HWPROBE_EXT_ZICBOZ
20710fca6ea1SDimitry Andric   Features["zbc"] = ExtMask & (1 << 7);         // RISCV_HWPROBE_EXT_ZBC
20720fca6ea1SDimitry Andric   Features["zbkb"] = ExtMask & (1 << 8);        // RISCV_HWPROBE_EXT_ZBKB
20730fca6ea1SDimitry Andric   Features["zbkc"] = ExtMask & (1 << 9);        // RISCV_HWPROBE_EXT_ZBKC
20740fca6ea1SDimitry Andric   Features["zbkx"] = ExtMask & (1 << 10);       // RISCV_HWPROBE_EXT_ZBKX
20750fca6ea1SDimitry Andric   Features["zknd"] = ExtMask & (1 << 11);       // RISCV_HWPROBE_EXT_ZKND
20760fca6ea1SDimitry Andric   Features["zkne"] = ExtMask & (1 << 12);       // RISCV_HWPROBE_EXT_ZKNE
20770fca6ea1SDimitry Andric   Features["zknh"] = ExtMask & (1 << 13);       // RISCV_HWPROBE_EXT_ZKNH
20780fca6ea1SDimitry Andric   Features["zksed"] = ExtMask & (1 << 14);      // RISCV_HWPROBE_EXT_ZKSED
20790fca6ea1SDimitry Andric   Features["zksh"] = ExtMask & (1 << 15);       // RISCV_HWPROBE_EXT_ZKSH
20800fca6ea1SDimitry Andric   Features["zkt"] = ExtMask & (1 << 16);        // RISCV_HWPROBE_EXT_ZKT
20810fca6ea1SDimitry Andric   Features["zvbb"] = ExtMask & (1 << 17);       // RISCV_HWPROBE_EXT_ZVBB
20820fca6ea1SDimitry Andric   Features["zvbc"] = ExtMask & (1 << 18);       // RISCV_HWPROBE_EXT_ZVBC
20830fca6ea1SDimitry Andric   Features["zvkb"] = ExtMask & (1 << 19);       // RISCV_HWPROBE_EXT_ZVKB
20840fca6ea1SDimitry Andric   Features["zvkg"] = ExtMask & (1 << 20);       // RISCV_HWPROBE_EXT_ZVKG
20850fca6ea1SDimitry Andric   Features["zvkned"] = ExtMask & (1 << 21);     // RISCV_HWPROBE_EXT_ZVKNED
20860fca6ea1SDimitry Andric   Features["zvknha"] = ExtMask & (1 << 22);     // RISCV_HWPROBE_EXT_ZVKNHA
20870fca6ea1SDimitry Andric   Features["zvknhb"] = ExtMask & (1 << 23);     // RISCV_HWPROBE_EXT_ZVKNHB
20880fca6ea1SDimitry Andric   Features["zvksed"] = ExtMask & (1 << 24);     // RISCV_HWPROBE_EXT_ZVKSED
20890fca6ea1SDimitry Andric   Features["zvksh"] = ExtMask & (1 << 25);      // RISCV_HWPROBE_EXT_ZVKSH
20900fca6ea1SDimitry Andric   Features["zvkt"] = ExtMask & (1 << 26);       // RISCV_HWPROBE_EXT_ZVKT
20910fca6ea1SDimitry Andric   Features["zfh"] = ExtMask & (1 << 27);        // RISCV_HWPROBE_EXT_ZFH
20920fca6ea1SDimitry Andric   Features["zfhmin"] = ExtMask & (1 << 28);     // RISCV_HWPROBE_EXT_ZFHMIN
20930fca6ea1SDimitry Andric   Features["zihintntl"] = ExtMask & (1 << 29);  // RISCV_HWPROBE_EXT_ZIHINTNTL
20940fca6ea1SDimitry Andric   Features["zvfh"] = ExtMask & (1 << 30);       // RISCV_HWPROBE_EXT_ZVFH
20950fca6ea1SDimitry Andric   Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN
20960fca6ea1SDimitry Andric   Features["zfa"] = ExtMask & (1ULL << 32);     // RISCV_HWPROBE_EXT_ZFA
20970fca6ea1SDimitry Andric   Features["ztso"] = ExtMask & (1ULL << 33);    // RISCV_HWPROBE_EXT_ZTSO
20980fca6ea1SDimitry Andric   // TODO: Re-enable zacas when it is marked non-experimental again.
20990fca6ea1SDimitry Andric   // Features["zacas"] = ExtMask & (1ULL << 34);   // RISCV_HWPROBE_EXT_ZACAS
21000fca6ea1SDimitry Andric   Features["zicond"] = ExtMask & (1ULL << 35);  // RISCV_HWPROBE_EXT_ZICOND
21010fca6ea1SDimitry Andric   Features["zihintpause"] =
21020fca6ea1SDimitry Andric       ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE
21030fca6ea1SDimitry Andric 
21040fca6ea1SDimitry Andric   // TODO: set unaligned-scalar-mem if RISCV_HWPROBE_KEY_MISALIGNED_PERF returns
21050fca6ea1SDimitry Andric   // RISCV_HWPROBE_MISALIGNED_FAST.
21060fca6ea1SDimitry Andric 
21070fca6ea1SDimitry Andric   return Features;
210806c3fb27SDimitry Andric }
2109bdd1243dSDimitry Andric #else
21100fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { return {}; }
2111bdd1243dSDimitry Andric #endif
2112bdd1243dSDimitry Andric 
211306c3fb27SDimitry Andric #if __APPLE__
211406c3fb27SDimitry Andric /// \returns the \p triple, but with the Host's arch spliced in.
211506c3fb27SDimitry Andric static Triple withHostArch(Triple T) {
211606c3fb27SDimitry Andric #if defined(__arm__)
211706c3fb27SDimitry Andric   T.setArch(Triple::arm);
211806c3fb27SDimitry Andric   T.setArchName("arm");
211906c3fb27SDimitry Andric #elif defined(__arm64e__)
212006c3fb27SDimitry Andric   T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);
212106c3fb27SDimitry Andric   T.setArchName("arm64e");
212206c3fb27SDimitry Andric #elif defined(__aarch64__)
212306c3fb27SDimitry Andric   T.setArch(Triple::aarch64);
212406c3fb27SDimitry Andric   T.setArchName("arm64");
212506c3fb27SDimitry Andric #elif defined(__x86_64h__)
212606c3fb27SDimitry Andric   T.setArch(Triple::x86_64);
212706c3fb27SDimitry Andric   T.setArchName("x86_64h");
212806c3fb27SDimitry Andric #elif defined(__x86_64__)
212906c3fb27SDimitry Andric   T.setArch(Triple::x86_64);
213006c3fb27SDimitry Andric   T.setArchName("x86_64");
21315f757f3fSDimitry Andric #elif defined(__i386__)
21325f757f3fSDimitry Andric   T.setArch(Triple::x86);
21335f757f3fSDimitry Andric   T.setArchName("i386");
213406c3fb27SDimitry Andric #elif defined(__powerpc__)
213506c3fb27SDimitry Andric   T.setArch(Triple::ppc);
213606c3fb27SDimitry Andric   T.setArchName("powerpc");
213706c3fb27SDimitry Andric #else
213806c3fb27SDimitry Andric #  error "Unimplemented host arch fixup"
213906c3fb27SDimitry Andric #endif
214006c3fb27SDimitry Andric   return T;
214106c3fb27SDimitry Andric }
214206c3fb27SDimitry Andric #endif
214306c3fb27SDimitry Andric 
2144bdd1243dSDimitry Andric std::string sys::getProcessTriple() {
2145bdd1243dSDimitry Andric   std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
2146bdd1243dSDimitry Andric   Triple PT(Triple::normalize(TargetTripleString));
2147bdd1243dSDimitry Andric 
214806c3fb27SDimitry Andric #if __APPLE__
214906c3fb27SDimitry Andric   /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of
215006c3fb27SDimitry Andric   /// the slices. This fixes that up.
215106c3fb27SDimitry Andric   PT = withHostArch(PT);
215206c3fb27SDimitry Andric #endif
215306c3fb27SDimitry Andric 
2154bdd1243dSDimitry Andric   if (sizeof(void *) == 8 && PT.isArch32Bit())
2155bdd1243dSDimitry Andric     PT = PT.get64BitArchVariant();
2156bdd1243dSDimitry Andric   if (sizeof(void *) == 4 && PT.isArch64Bit())
2157bdd1243dSDimitry Andric     PT = PT.get32BitArchVariant();
2158bdd1243dSDimitry Andric 
2159bdd1243dSDimitry Andric   return PT.str();
2160bdd1243dSDimitry Andric }
2161bdd1243dSDimitry Andric 
2162bdd1243dSDimitry Andric void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {
2163bdd1243dSDimitry Andric #if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
2164bdd1243dSDimitry Andric   std::string CPU = std::string(sys::getHostCPUName());
2165bdd1243dSDimitry Andric   if (CPU == "generic")
2166bdd1243dSDimitry Andric     CPU = "(unknown)";
2167bdd1243dSDimitry Andric   OS << "  Default target: " << sys::getDefaultTargetTriple() << '\n'
2168bdd1243dSDimitry Andric      << "  Host CPU: " << CPU << '\n';
2169bdd1243dSDimitry Andric #endif
2170bdd1243dSDimitry Andric }
2171