xref: /freebsd-src/contrib/llvm-project/llvm/lib/TargetParser/Host.cpp (revision 8a4dda33d67586ca2624f2a38417baa03a533a7f)
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")
153bdd1243dSDimitry Andric       // FIXME: If we get a simulator or machine with the capabilities of
154bdd1243dSDimitry Andric       // mcpu=future, we should revisit this and add the name reported by the
155bdd1243dSDimitry Andric       // simulator/machine.
156bdd1243dSDimitry Andric       .Default(generic);
157bdd1243dSDimitry Andric }
158bdd1243dSDimitry Andric 
159bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
160bdd1243dSDimitry Andric   // The cpuid register on arm is not accessible from user space. On Linux,
161bdd1243dSDimitry Andric   // it is exposed through the /proc/cpuinfo file.
162bdd1243dSDimitry Andric 
163bdd1243dSDimitry Andric   // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
164bdd1243dSDimitry Andric   // in all cases.
165bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
166bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
167bdd1243dSDimitry Andric 
168bdd1243dSDimitry Andric   // Look for the CPU implementer line.
169bdd1243dSDimitry Andric   StringRef Implementer;
170bdd1243dSDimitry Andric   StringRef Hardware;
171bdd1243dSDimitry Andric   StringRef Part;
172bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
173bdd1243dSDimitry Andric     if (Lines[I].startswith("CPU implementer"))
174bdd1243dSDimitry Andric       Implementer = Lines[I].substr(15).ltrim("\t :");
175bdd1243dSDimitry Andric     if (Lines[I].startswith("Hardware"))
176bdd1243dSDimitry Andric       Hardware = Lines[I].substr(8).ltrim("\t :");
177bdd1243dSDimitry Andric     if (Lines[I].startswith("CPU part"))
178bdd1243dSDimitry Andric       Part = Lines[I].substr(8).ltrim("\t :");
179bdd1243dSDimitry Andric   }
180bdd1243dSDimitry Andric 
181bdd1243dSDimitry Andric   if (Implementer == "0x41") { // ARM Ltd.
182bdd1243dSDimitry Andric     // MSM8992/8994 may give cpu part for the core that the kernel is running on,
183bdd1243dSDimitry Andric     // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
184bdd1243dSDimitry Andric     if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996"))
185bdd1243dSDimitry Andric       return "cortex-a53";
186bdd1243dSDimitry Andric 
187bdd1243dSDimitry Andric 
188bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
189bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
190bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
191bdd1243dSDimitry Andric     // This corresponds to the Main ID Register in Technical Reference Manuals.
192bdd1243dSDimitry Andric     // and is used in programs like sys-utils
193bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
194bdd1243dSDimitry Andric         .Case("0x926", "arm926ej-s")
195bdd1243dSDimitry Andric         .Case("0xb02", "mpcore")
196bdd1243dSDimitry Andric         .Case("0xb36", "arm1136j-s")
197bdd1243dSDimitry Andric         .Case("0xb56", "arm1156t2-s")
198bdd1243dSDimitry Andric         .Case("0xb76", "arm1176jz-s")
199bdd1243dSDimitry Andric         .Case("0xc08", "cortex-a8")
200bdd1243dSDimitry Andric         .Case("0xc09", "cortex-a9")
201bdd1243dSDimitry Andric         .Case("0xc0f", "cortex-a15")
202bdd1243dSDimitry Andric         .Case("0xc20", "cortex-m0")
203bdd1243dSDimitry Andric         .Case("0xc23", "cortex-m3")
204bdd1243dSDimitry Andric         .Case("0xc24", "cortex-m4")
205bdd1243dSDimitry Andric         .Case("0xd22", "cortex-m55")
206bdd1243dSDimitry Andric         .Case("0xd02", "cortex-a34")
207bdd1243dSDimitry Andric         .Case("0xd04", "cortex-a35")
208bdd1243dSDimitry Andric         .Case("0xd03", "cortex-a53")
209bdd1243dSDimitry Andric         .Case("0xd05", "cortex-a55")
210bdd1243dSDimitry Andric         .Case("0xd46", "cortex-a510")
211bdd1243dSDimitry Andric         .Case("0xd07", "cortex-a57")
212bdd1243dSDimitry Andric         .Case("0xd08", "cortex-a72")
213bdd1243dSDimitry Andric         .Case("0xd09", "cortex-a73")
214bdd1243dSDimitry Andric         .Case("0xd0a", "cortex-a75")
215bdd1243dSDimitry Andric         .Case("0xd0b", "cortex-a76")
216bdd1243dSDimitry Andric         .Case("0xd0d", "cortex-a77")
217bdd1243dSDimitry Andric         .Case("0xd41", "cortex-a78")
218bdd1243dSDimitry Andric         .Case("0xd47", "cortex-a710")
219bdd1243dSDimitry Andric         .Case("0xd4d", "cortex-a715")
220bdd1243dSDimitry Andric         .Case("0xd44", "cortex-x1")
221bdd1243dSDimitry Andric         .Case("0xd4c", "cortex-x1c")
222bdd1243dSDimitry Andric         .Case("0xd48", "cortex-x2")
223bdd1243dSDimitry Andric         .Case("0xd4e", "cortex-x3")
224bdd1243dSDimitry Andric         .Case("0xd0c", "neoverse-n1")
225bdd1243dSDimitry Andric         .Case("0xd49", "neoverse-n2")
226bdd1243dSDimitry Andric         .Case("0xd40", "neoverse-v1")
227bdd1243dSDimitry Andric         .Case("0xd4f", "neoverse-v2")
228bdd1243dSDimitry Andric         .Default("generic");
229bdd1243dSDimitry Andric   }
230bdd1243dSDimitry Andric 
231bdd1243dSDimitry Andric   if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
232bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
233bdd1243dSDimitry Andric       .Case("0x516", "thunderx2t99")
234bdd1243dSDimitry Andric       .Case("0x0516", "thunderx2t99")
235bdd1243dSDimitry Andric       .Case("0xaf", "thunderx2t99")
236bdd1243dSDimitry Andric       .Case("0x0af", "thunderx2t99")
237bdd1243dSDimitry Andric       .Case("0xa1", "thunderxt88")
238bdd1243dSDimitry Andric       .Case("0x0a1", "thunderxt88")
239bdd1243dSDimitry Andric       .Default("generic");
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric 
242bdd1243dSDimitry Andric   if (Implementer == "0x46") { // Fujitsu Ltd.
243bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
244bdd1243dSDimitry Andric       .Case("0x001", "a64fx")
245bdd1243dSDimitry Andric       .Default("generic");
246bdd1243dSDimitry Andric   }
247bdd1243dSDimitry Andric 
248bdd1243dSDimitry Andric   if (Implementer == "0x4e") { // NVIDIA Corporation
249bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
250bdd1243dSDimitry Andric         .Case("0x004", "carmel")
251bdd1243dSDimitry Andric         .Default("generic");
252bdd1243dSDimitry Andric   }
253bdd1243dSDimitry Andric 
254bdd1243dSDimitry Andric   if (Implementer == "0x48") // HiSilicon Technologies, Inc.
255bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
256bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
257bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
258bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
259bdd1243dSDimitry Andric       .Case("0xd01", "tsv110")
260bdd1243dSDimitry Andric       .Default("generic");
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric   if (Implementer == "0x51") // Qualcomm Technologies, Inc.
263bdd1243dSDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
264bdd1243dSDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
265bdd1243dSDimitry Andric     // contents are specified in the various processor manuals.
266bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
267bdd1243dSDimitry Andric         .Case("0x06f", "krait") // APQ8064
268bdd1243dSDimitry Andric         .Case("0x201", "kryo")
269bdd1243dSDimitry Andric         .Case("0x205", "kryo")
270bdd1243dSDimitry Andric         .Case("0x211", "kryo")
271bdd1243dSDimitry Andric         .Case("0x800", "cortex-a73") // Kryo 2xx Gold
272bdd1243dSDimitry Andric         .Case("0x801", "cortex-a73") // Kryo 2xx Silver
273bdd1243dSDimitry Andric         .Case("0x802", "cortex-a75") // Kryo 3xx Gold
274bdd1243dSDimitry Andric         .Case("0x803", "cortex-a75") // Kryo 3xx Silver
275bdd1243dSDimitry Andric         .Case("0x804", "cortex-a76") // Kryo 4xx Gold
276bdd1243dSDimitry Andric         .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver
277bdd1243dSDimitry Andric         .Case("0xc00", "falkor")
278bdd1243dSDimitry Andric         .Case("0xc01", "saphira")
279bdd1243dSDimitry Andric         .Default("generic");
280bdd1243dSDimitry Andric   if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
281bdd1243dSDimitry Andric     // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
282bdd1243dSDimitry Andric     // any predictive pattern across variants and parts.
283bdd1243dSDimitry Andric     unsigned Variant = 0, Part = 0;
284bdd1243dSDimitry Andric 
285bdd1243dSDimitry Andric     // Look for the CPU variant line, whose value is a 1 digit hexadecimal
286bdd1243dSDimitry Andric     // number, corresponding to the Variant bits in the CP15/C0 register.
287bdd1243dSDimitry Andric     for (auto I : Lines)
288bdd1243dSDimitry Andric       if (I.consume_front("CPU variant"))
289bdd1243dSDimitry Andric         I.ltrim("\t :").getAsInteger(0, Variant);
290bdd1243dSDimitry Andric 
291bdd1243dSDimitry Andric     // Look for the CPU part line, whose value is a 3 digit hexadecimal
292bdd1243dSDimitry Andric     // number, corresponding to the PartNum bits in the CP15/C0 register.
293bdd1243dSDimitry Andric     for (auto I : Lines)
294bdd1243dSDimitry Andric       if (I.consume_front("CPU part"))
295bdd1243dSDimitry Andric         I.ltrim("\t :").getAsInteger(0, Part);
296bdd1243dSDimitry Andric 
297bdd1243dSDimitry Andric     unsigned Exynos = (Variant << 12) | Part;
298bdd1243dSDimitry Andric     switch (Exynos) {
299bdd1243dSDimitry Andric     default:
300bdd1243dSDimitry Andric       // Default by falling through to Exynos M3.
301bdd1243dSDimitry Andric       [[fallthrough]];
302bdd1243dSDimitry Andric     case 0x1002:
303bdd1243dSDimitry Andric       return "exynos-m3";
304bdd1243dSDimitry Andric     case 0x1003:
305bdd1243dSDimitry Andric       return "exynos-m4";
306bdd1243dSDimitry Andric     }
307bdd1243dSDimitry Andric   }
308bdd1243dSDimitry Andric 
309bdd1243dSDimitry Andric   if (Implementer == "0xc0") { // Ampere Computing
310bdd1243dSDimitry Andric     return StringSwitch<const char *>(Part)
311bdd1243dSDimitry Andric         .Case("0xac3", "ampere1")
312bdd1243dSDimitry Andric         .Case("0xac4", "ampere1a")
313bdd1243dSDimitry Andric         .Default("generic");
314bdd1243dSDimitry Andric   }
315bdd1243dSDimitry Andric 
316bdd1243dSDimitry Andric   return "generic";
317bdd1243dSDimitry Andric }
318bdd1243dSDimitry Andric 
319bdd1243dSDimitry Andric namespace {
320bdd1243dSDimitry Andric StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {
321bdd1243dSDimitry Andric   switch (Id) {
322bdd1243dSDimitry Andric     case 2064:  // z900 not supported by LLVM
323bdd1243dSDimitry Andric     case 2066:
324bdd1243dSDimitry Andric     case 2084:  // z990 not supported by LLVM
325bdd1243dSDimitry Andric     case 2086:
326bdd1243dSDimitry Andric     case 2094:  // z9-109 not supported by LLVM
327bdd1243dSDimitry Andric     case 2096:
328bdd1243dSDimitry Andric       return "generic";
329bdd1243dSDimitry Andric     case 2097:
330bdd1243dSDimitry Andric     case 2098:
331bdd1243dSDimitry Andric       return "z10";
332bdd1243dSDimitry Andric     case 2817:
333bdd1243dSDimitry Andric     case 2818:
334bdd1243dSDimitry Andric       return "z196";
335bdd1243dSDimitry Andric     case 2827:
336bdd1243dSDimitry Andric     case 2828:
337bdd1243dSDimitry Andric       return "zEC12";
338bdd1243dSDimitry Andric     case 2964:
339bdd1243dSDimitry Andric     case 2965:
340bdd1243dSDimitry Andric       return HaveVectorSupport? "z13" : "zEC12";
341bdd1243dSDimitry Andric     case 3906:
342bdd1243dSDimitry Andric     case 3907:
343bdd1243dSDimitry Andric       return HaveVectorSupport? "z14" : "zEC12";
344bdd1243dSDimitry Andric     case 8561:
345bdd1243dSDimitry Andric     case 8562:
346bdd1243dSDimitry Andric       return HaveVectorSupport? "z15" : "zEC12";
347bdd1243dSDimitry Andric     case 3931:
348bdd1243dSDimitry Andric     case 3932:
349bdd1243dSDimitry Andric     default:
350bdd1243dSDimitry Andric       return HaveVectorSupport? "z16" : "zEC12";
351bdd1243dSDimitry Andric   }
352bdd1243dSDimitry Andric }
353bdd1243dSDimitry Andric } // end anonymous namespace
354bdd1243dSDimitry Andric 
355bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
356bdd1243dSDimitry Andric   // STIDP is a privileged operation, so use /proc/cpuinfo instead.
357bdd1243dSDimitry Andric 
358bdd1243dSDimitry Andric   // The "processor 0:" line comes after a fair amount of other information,
359bdd1243dSDimitry Andric   // including a cache breakdown, but this should be plenty.
360bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
361bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
362bdd1243dSDimitry Andric 
363bdd1243dSDimitry Andric   // Look for the CPU features.
364bdd1243dSDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
365bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
366bdd1243dSDimitry Andric     if (Lines[I].startswith("features")) {
367bdd1243dSDimitry Andric       size_t Pos = Lines[I].find(':');
368bdd1243dSDimitry Andric       if (Pos != StringRef::npos) {
369bdd1243dSDimitry Andric         Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
370bdd1243dSDimitry Andric         break;
371bdd1243dSDimitry Andric       }
372bdd1243dSDimitry Andric     }
373bdd1243dSDimitry Andric 
374bdd1243dSDimitry Andric   // We need to check for the presence of vector support independently of
375bdd1243dSDimitry Andric   // the machine type, since we may only use the vector register set when
376bdd1243dSDimitry Andric   // supported by the kernel (and hypervisor).
377bdd1243dSDimitry Andric   bool HaveVectorSupport = false;
378bdd1243dSDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
379bdd1243dSDimitry Andric     if (CPUFeatures[I] == "vx")
380bdd1243dSDimitry Andric       HaveVectorSupport = true;
381bdd1243dSDimitry Andric   }
382bdd1243dSDimitry Andric 
383bdd1243dSDimitry Andric   // Now check the processor machine type.
384bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
385bdd1243dSDimitry Andric     if (Lines[I].startswith("processor ")) {
386bdd1243dSDimitry Andric       size_t Pos = Lines[I].find("machine = ");
387bdd1243dSDimitry Andric       if (Pos != StringRef::npos) {
388bdd1243dSDimitry Andric         Pos += sizeof("machine = ") - 1;
389bdd1243dSDimitry Andric         unsigned int Id;
390bdd1243dSDimitry Andric         if (!Lines[I].drop_front(Pos).getAsInteger(10, Id))
391bdd1243dSDimitry Andric           return getCPUNameFromS390Model(Id, HaveVectorSupport);
392bdd1243dSDimitry Andric       }
393bdd1243dSDimitry Andric       break;
394bdd1243dSDimitry Andric     }
395bdd1243dSDimitry Andric   }
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric   return "generic";
398bdd1243dSDimitry Andric }
399bdd1243dSDimitry Andric 
400bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {
401bdd1243dSDimitry Andric   // There are 24 lines in /proc/cpuinfo
402bdd1243dSDimitry Andric   SmallVector<StringRef> Lines;
403bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
404bdd1243dSDimitry Andric 
405bdd1243dSDimitry Andric   // Look for uarch line to determine cpu name
406bdd1243dSDimitry Andric   StringRef UArch;
407bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
408bdd1243dSDimitry Andric     if (Lines[I].startswith("uarch")) {
409bdd1243dSDimitry Andric       UArch = Lines[I].substr(5).ltrim("\t :");
410bdd1243dSDimitry Andric       break;
411bdd1243dSDimitry Andric     }
412bdd1243dSDimitry Andric   }
413bdd1243dSDimitry Andric 
414bdd1243dSDimitry Andric   return StringSwitch<const char *>(UArch)
415bdd1243dSDimitry Andric       .Case("sifive,u74-mc", "sifive-u74")
416bdd1243dSDimitry Andric       .Case("sifive,bullet0", "sifive-u74")
417bdd1243dSDimitry Andric       .Default("generic");
418bdd1243dSDimitry Andric }
419bdd1243dSDimitry Andric 
420bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForBPF() {
421bdd1243dSDimitry Andric #if !defined(__linux__) || !defined(__x86_64__)
422bdd1243dSDimitry Andric   return "generic";
423bdd1243dSDimitry Andric #else
424bdd1243dSDimitry Andric   uint8_t v3_insns[40] __attribute__ ((aligned (8))) =
425bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
426bdd1243dSDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
427bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
428bdd1243dSDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
429bdd1243dSDimitry Andric       /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
430bdd1243dSDimitry Andric       0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
431bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
432bdd1243dSDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
433bdd1243dSDimitry Andric       /* BPF_EXIT_INSN() */
434bdd1243dSDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
435bdd1243dSDimitry Andric 
436bdd1243dSDimitry Andric   uint8_t v2_insns[40] __attribute__ ((aligned (8))) =
437bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
438bdd1243dSDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
439bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
440bdd1243dSDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
441bdd1243dSDimitry Andric       /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
442bdd1243dSDimitry Andric       0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
443bdd1243dSDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
444bdd1243dSDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
445bdd1243dSDimitry Andric       /* BPF_EXIT_INSN() */
446bdd1243dSDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
447bdd1243dSDimitry Andric 
448bdd1243dSDimitry Andric   struct bpf_prog_load_attr {
449bdd1243dSDimitry Andric     uint32_t prog_type;
450bdd1243dSDimitry Andric     uint32_t insn_cnt;
451bdd1243dSDimitry Andric     uint64_t insns;
452bdd1243dSDimitry Andric     uint64_t license;
453bdd1243dSDimitry Andric     uint32_t log_level;
454bdd1243dSDimitry Andric     uint32_t log_size;
455bdd1243dSDimitry Andric     uint64_t log_buf;
456bdd1243dSDimitry Andric     uint32_t kern_version;
457bdd1243dSDimitry Andric     uint32_t prog_flags;
458bdd1243dSDimitry Andric   } attr = {};
459bdd1243dSDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
460bdd1243dSDimitry Andric   attr.insn_cnt = 5;
461bdd1243dSDimitry Andric   attr.insns = (uint64_t)v3_insns;
462bdd1243dSDimitry Andric   attr.license = (uint64_t)"DUMMY";
463bdd1243dSDimitry Andric 
464bdd1243dSDimitry Andric   int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,
465bdd1243dSDimitry Andric                    sizeof(attr));
466bdd1243dSDimitry Andric   if (fd >= 0) {
467bdd1243dSDimitry Andric     close(fd);
468bdd1243dSDimitry Andric     return "v3";
469bdd1243dSDimitry Andric   }
470bdd1243dSDimitry Andric 
471bdd1243dSDimitry Andric   /* Clear the whole attr in case its content changed by syscall. */
472bdd1243dSDimitry Andric   memset(&attr, 0, sizeof(attr));
473bdd1243dSDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
474bdd1243dSDimitry Andric   attr.insn_cnt = 5;
475bdd1243dSDimitry Andric   attr.insns = (uint64_t)v2_insns;
476bdd1243dSDimitry Andric   attr.license = (uint64_t)"DUMMY";
477bdd1243dSDimitry Andric   fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
478bdd1243dSDimitry Andric   if (fd >= 0) {
479bdd1243dSDimitry Andric     close(fd);
480bdd1243dSDimitry Andric     return "v2";
481bdd1243dSDimitry Andric   }
482bdd1243dSDimitry Andric   return "v1";
483bdd1243dSDimitry Andric #endif
484bdd1243dSDimitry Andric }
485bdd1243dSDimitry Andric 
486bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
487bdd1243dSDimitry Andric     defined(__x86_64__) || defined(_M_X64)
488bdd1243dSDimitry Andric 
489bdd1243dSDimitry Andric // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
490bdd1243dSDimitry Andric // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
491bdd1243dSDimitry Andric // support. Consequently, for i386, the presence of CPUID is checked first
492bdd1243dSDimitry Andric // via the corresponding eflags bit.
493bdd1243dSDimitry Andric // Removal of cpuid.h header motivated by PR30384
494bdd1243dSDimitry Andric // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
495bdd1243dSDimitry Andric // or test-suite, but are used in external projects e.g. libstdcxx
496bdd1243dSDimitry Andric static bool isCpuIdSupported() {
497bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
498bdd1243dSDimitry Andric #if defined(__i386__)
499bdd1243dSDimitry Andric   int __cpuid_supported;
500bdd1243dSDimitry Andric   __asm__("  pushfl\n"
501bdd1243dSDimitry Andric           "  popl   %%eax\n"
502bdd1243dSDimitry Andric           "  movl   %%eax,%%ecx\n"
503bdd1243dSDimitry Andric           "  xorl   $0x00200000,%%eax\n"
504bdd1243dSDimitry Andric           "  pushl  %%eax\n"
505bdd1243dSDimitry Andric           "  popfl\n"
506bdd1243dSDimitry Andric           "  pushfl\n"
507bdd1243dSDimitry Andric           "  popl   %%eax\n"
508bdd1243dSDimitry Andric           "  movl   $0,%0\n"
509bdd1243dSDimitry Andric           "  cmpl   %%eax,%%ecx\n"
510bdd1243dSDimitry Andric           "  je     1f\n"
511bdd1243dSDimitry Andric           "  movl   $1,%0\n"
512bdd1243dSDimitry Andric           "1:"
513bdd1243dSDimitry Andric           : "=r"(__cpuid_supported)
514bdd1243dSDimitry Andric           :
515bdd1243dSDimitry Andric           : "eax", "ecx");
516bdd1243dSDimitry Andric   if (!__cpuid_supported)
517bdd1243dSDimitry Andric     return false;
518bdd1243dSDimitry Andric #endif
519bdd1243dSDimitry Andric   return true;
520bdd1243dSDimitry Andric #endif
521bdd1243dSDimitry Andric   return true;
522bdd1243dSDimitry Andric }
523bdd1243dSDimitry Andric 
524bdd1243dSDimitry Andric /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
525bdd1243dSDimitry Andric /// the specified arguments.  If we can't run cpuid on the host, return true.
526bdd1243dSDimitry Andric static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
527bdd1243dSDimitry Andric                                unsigned *rECX, unsigned *rEDX) {
528bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
529bdd1243dSDimitry Andric #if defined(__x86_64__)
530bdd1243dSDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
531bdd1243dSDimitry Andric   // FIXME: should we save this for Clang?
532bdd1243dSDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
533bdd1243dSDimitry Andric           "cpuid\n\t"
534bdd1243dSDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
535bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
536bdd1243dSDimitry Andric           : "a"(value));
537bdd1243dSDimitry Andric   return false;
538bdd1243dSDimitry Andric #elif defined(__i386__)
539bdd1243dSDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
540bdd1243dSDimitry Andric           "cpuid\n\t"
541bdd1243dSDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
542bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
543bdd1243dSDimitry Andric           : "a"(value));
544bdd1243dSDimitry Andric   return false;
545bdd1243dSDimitry Andric #else
546bdd1243dSDimitry Andric   return true;
547bdd1243dSDimitry Andric #endif
548bdd1243dSDimitry Andric #elif defined(_MSC_VER)
549bdd1243dSDimitry Andric   // The MSVC intrinsic is portable across x86 and x64.
550bdd1243dSDimitry Andric   int registers[4];
551bdd1243dSDimitry Andric   __cpuid(registers, value);
552bdd1243dSDimitry Andric   *rEAX = registers[0];
553bdd1243dSDimitry Andric   *rEBX = registers[1];
554bdd1243dSDimitry Andric   *rECX = registers[2];
555bdd1243dSDimitry Andric   *rEDX = registers[3];
556bdd1243dSDimitry Andric   return false;
557bdd1243dSDimitry Andric #else
558bdd1243dSDimitry Andric   return true;
559bdd1243dSDimitry Andric #endif
560bdd1243dSDimitry Andric }
561bdd1243dSDimitry Andric 
562bdd1243dSDimitry Andric namespace llvm {
563bdd1243dSDimitry Andric namespace sys {
564bdd1243dSDimitry Andric namespace detail {
565bdd1243dSDimitry Andric namespace x86 {
566bdd1243dSDimitry Andric 
567bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
568bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
569bdd1243dSDimitry Andric   if (MaxLeaf == nullptr)
570bdd1243dSDimitry Andric     MaxLeaf = &EAX;
571bdd1243dSDimitry Andric   else
572bdd1243dSDimitry Andric     *MaxLeaf = 0;
573bdd1243dSDimitry Andric 
574bdd1243dSDimitry Andric   if (!isCpuIdSupported())
575bdd1243dSDimitry Andric     return VendorSignatures::UNKNOWN;
576bdd1243dSDimitry Andric 
577bdd1243dSDimitry Andric   if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)
578bdd1243dSDimitry Andric     return VendorSignatures::UNKNOWN;
579bdd1243dSDimitry Andric 
580bdd1243dSDimitry Andric   // "Genu ineI ntel"
581bdd1243dSDimitry Andric   if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)
582bdd1243dSDimitry Andric     return VendorSignatures::GENUINE_INTEL;
583bdd1243dSDimitry Andric 
584bdd1243dSDimitry Andric   // "Auth enti cAMD"
585bdd1243dSDimitry Andric   if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)
586bdd1243dSDimitry Andric     return VendorSignatures::AUTHENTIC_AMD;
587bdd1243dSDimitry Andric 
588bdd1243dSDimitry Andric   return VendorSignatures::UNKNOWN;
589bdd1243dSDimitry Andric }
590bdd1243dSDimitry Andric 
591bdd1243dSDimitry Andric } // namespace x86
592bdd1243dSDimitry Andric } // namespace detail
593bdd1243dSDimitry Andric } // namespace sys
594bdd1243dSDimitry Andric } // namespace llvm
595bdd1243dSDimitry Andric 
596bdd1243dSDimitry Andric using namespace llvm::sys::detail::x86;
597bdd1243dSDimitry Andric 
598bdd1243dSDimitry Andric /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
599bdd1243dSDimitry Andric /// the 4 values in the specified arguments.  If we can't run cpuid on the host,
600bdd1243dSDimitry Andric /// return true.
601bdd1243dSDimitry Andric static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
602bdd1243dSDimitry Andric                                  unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
603bdd1243dSDimitry Andric                                  unsigned *rEDX) {
604bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
605bdd1243dSDimitry Andric #if defined(__x86_64__)
606bdd1243dSDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
607bdd1243dSDimitry Andric   // FIXME: should we save this for Clang?
608bdd1243dSDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
609bdd1243dSDimitry Andric           "cpuid\n\t"
610bdd1243dSDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
611bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
612bdd1243dSDimitry Andric           : "a"(value), "c"(subleaf));
613bdd1243dSDimitry Andric   return false;
614bdd1243dSDimitry Andric #elif defined(__i386__)
615bdd1243dSDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
616bdd1243dSDimitry Andric           "cpuid\n\t"
617bdd1243dSDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
618bdd1243dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
619bdd1243dSDimitry Andric           : "a"(value), "c"(subleaf));
620bdd1243dSDimitry Andric   return false;
621bdd1243dSDimitry Andric #else
622bdd1243dSDimitry Andric   return true;
623bdd1243dSDimitry Andric #endif
624bdd1243dSDimitry Andric #elif defined(_MSC_VER)
625bdd1243dSDimitry Andric   int registers[4];
626bdd1243dSDimitry Andric   __cpuidex(registers, value, subleaf);
627bdd1243dSDimitry Andric   *rEAX = registers[0];
628bdd1243dSDimitry Andric   *rEBX = registers[1];
629bdd1243dSDimitry Andric   *rECX = registers[2];
630bdd1243dSDimitry Andric   *rEDX = registers[3];
631bdd1243dSDimitry Andric   return false;
632bdd1243dSDimitry Andric #else
633bdd1243dSDimitry Andric   return true;
634bdd1243dSDimitry Andric #endif
635bdd1243dSDimitry Andric }
636bdd1243dSDimitry Andric 
637bdd1243dSDimitry Andric // Read control register 0 (XCR0). Used to detect features such as AVX.
638bdd1243dSDimitry Andric static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
639bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__)
640bdd1243dSDimitry Andric   // Check xgetbv; this uses a .byte sequence instead of the instruction
641bdd1243dSDimitry Andric   // directly because older assemblers do not include support for xgetbv and
642bdd1243dSDimitry Andric   // there is no easy way to conditionally compile based on the assembler used.
643bdd1243dSDimitry Andric   __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
644bdd1243dSDimitry Andric   return false;
645bdd1243dSDimitry Andric #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
646bdd1243dSDimitry Andric   unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
647bdd1243dSDimitry Andric   *rEAX = Result;
648bdd1243dSDimitry Andric   *rEDX = Result >> 32;
649bdd1243dSDimitry Andric   return false;
650bdd1243dSDimitry Andric #else
651bdd1243dSDimitry Andric   return true;
652bdd1243dSDimitry Andric #endif
653bdd1243dSDimitry Andric }
654bdd1243dSDimitry Andric 
655bdd1243dSDimitry Andric static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
656bdd1243dSDimitry Andric                                  unsigned *Model) {
657bdd1243dSDimitry Andric   *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
658bdd1243dSDimitry Andric   *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
659bdd1243dSDimitry Andric   if (*Family == 6 || *Family == 0xf) {
660bdd1243dSDimitry Andric     if (*Family == 0xf)
661bdd1243dSDimitry Andric       // Examine extended family ID if family ID is F.
662bdd1243dSDimitry Andric       *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
663bdd1243dSDimitry Andric     // Examine extended model ID if family ID is 6 or F.
664bdd1243dSDimitry Andric     *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
665bdd1243dSDimitry Andric   }
666bdd1243dSDimitry Andric }
667bdd1243dSDimitry Andric 
668bdd1243dSDimitry Andric static StringRef
669bdd1243dSDimitry Andric getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
670bdd1243dSDimitry Andric                                 const unsigned *Features,
671bdd1243dSDimitry Andric                                 unsigned *Type, unsigned *Subtype) {
672bdd1243dSDimitry Andric   auto testFeature = [&](unsigned F) {
673bdd1243dSDimitry Andric     return (Features[F / 32] & (1U << (F % 32))) != 0;
674bdd1243dSDimitry Andric   };
675bdd1243dSDimitry Andric 
676bdd1243dSDimitry Andric   StringRef CPU;
677bdd1243dSDimitry Andric 
678bdd1243dSDimitry Andric   switch (Family) {
679bdd1243dSDimitry Andric   case 3:
680bdd1243dSDimitry Andric     CPU = "i386";
681bdd1243dSDimitry Andric     break;
682bdd1243dSDimitry Andric   case 4:
683bdd1243dSDimitry Andric     CPU = "i486";
684bdd1243dSDimitry Andric     break;
685bdd1243dSDimitry Andric   case 5:
686bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_MMX)) {
687bdd1243dSDimitry Andric       CPU = "pentium-mmx";
688bdd1243dSDimitry Andric       break;
689bdd1243dSDimitry Andric     }
690bdd1243dSDimitry Andric     CPU = "pentium";
691bdd1243dSDimitry Andric     break;
692bdd1243dSDimitry Andric   case 6:
693bdd1243dSDimitry Andric     switch (Model) {
694bdd1243dSDimitry Andric     case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
695bdd1243dSDimitry Andric                // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
696bdd1243dSDimitry Andric                // mobile processor, Intel Core 2 Extreme processor, Intel
697bdd1243dSDimitry Andric                // Pentium Dual-Core processor, Intel Xeon processor, model
698bdd1243dSDimitry Andric                // 0Fh. All processors are manufactured using the 65 nm process.
699bdd1243dSDimitry Andric     case 0x16: // Intel Celeron processor model 16h. All processors are
700bdd1243dSDimitry Andric                // manufactured using the 65 nm process
701bdd1243dSDimitry Andric       CPU = "core2";
702bdd1243dSDimitry Andric       *Type = X86::INTEL_CORE2;
703bdd1243dSDimitry Andric       break;
704bdd1243dSDimitry Andric     case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
705bdd1243dSDimitry Andric                // 17h. All processors are manufactured using the 45 nm process.
706bdd1243dSDimitry Andric                //
707bdd1243dSDimitry Andric                // 45nm: Penryn , Wolfdale, Yorkfield (XE)
708bdd1243dSDimitry Andric     case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
709bdd1243dSDimitry Andric                // the 45 nm process.
710bdd1243dSDimitry Andric       CPU = "penryn";
711bdd1243dSDimitry Andric       *Type = X86::INTEL_CORE2;
712bdd1243dSDimitry Andric       break;
713bdd1243dSDimitry Andric     case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
714bdd1243dSDimitry Andric                // processors are manufactured using the 45 nm process.
715bdd1243dSDimitry Andric     case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
716bdd1243dSDimitry Andric                // As found in a Summer 2010 model iMac.
717bdd1243dSDimitry Andric     case 0x1f:
718bdd1243dSDimitry Andric     case 0x2e:              // Nehalem EX
719bdd1243dSDimitry Andric       CPU = "nehalem";
720bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
721bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_NEHALEM;
722bdd1243dSDimitry Andric       break;
723bdd1243dSDimitry Andric     case 0x25: // Intel Core i7, laptop version.
724bdd1243dSDimitry Andric     case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
725bdd1243dSDimitry Andric                // processors are manufactured using the 32 nm process.
726bdd1243dSDimitry Andric     case 0x2f: // Westmere EX
727bdd1243dSDimitry Andric       CPU = "westmere";
728bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
729bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_WESTMERE;
730bdd1243dSDimitry Andric       break;
731bdd1243dSDimitry Andric     case 0x2a: // Intel Core i7 processor. All processors are manufactured
732bdd1243dSDimitry Andric                // using the 32 nm process.
733bdd1243dSDimitry Andric     case 0x2d:
734bdd1243dSDimitry Andric       CPU = "sandybridge";
735bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
736bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
737bdd1243dSDimitry Andric       break;
738bdd1243dSDimitry Andric     case 0x3a:
739bdd1243dSDimitry Andric     case 0x3e:              // Ivy Bridge EP
740bdd1243dSDimitry Andric       CPU = "ivybridge";
741bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
742bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
743bdd1243dSDimitry Andric       break;
744bdd1243dSDimitry Andric 
745bdd1243dSDimitry Andric     // Haswell:
746bdd1243dSDimitry Andric     case 0x3c:
747bdd1243dSDimitry Andric     case 0x3f:
748bdd1243dSDimitry Andric     case 0x45:
749bdd1243dSDimitry Andric     case 0x46:
750bdd1243dSDimitry Andric       CPU = "haswell";
751bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
752bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_HASWELL;
753bdd1243dSDimitry Andric       break;
754bdd1243dSDimitry Andric 
755bdd1243dSDimitry Andric     // Broadwell:
756bdd1243dSDimitry Andric     case 0x3d:
757bdd1243dSDimitry Andric     case 0x47:
758bdd1243dSDimitry Andric     case 0x4f:
759bdd1243dSDimitry Andric     case 0x56:
760bdd1243dSDimitry Andric       CPU = "broadwell";
761bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
762bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_BROADWELL;
763bdd1243dSDimitry Andric       break;
764bdd1243dSDimitry Andric 
765bdd1243dSDimitry Andric     // Skylake:
766bdd1243dSDimitry Andric     case 0x4e:              // Skylake mobile
767bdd1243dSDimitry Andric     case 0x5e:              // Skylake desktop
768bdd1243dSDimitry Andric     case 0x8e:              // Kaby Lake mobile
769bdd1243dSDimitry Andric     case 0x9e:              // Kaby Lake desktop
770bdd1243dSDimitry Andric     case 0xa5:              // Comet Lake-H/S
771bdd1243dSDimitry Andric     case 0xa6:              // Comet Lake-U
772bdd1243dSDimitry Andric       CPU = "skylake";
773bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
774bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SKYLAKE;
775bdd1243dSDimitry Andric       break;
776bdd1243dSDimitry Andric 
777bdd1243dSDimitry Andric     // Rocketlake:
778bdd1243dSDimitry Andric     case 0xa7:
779bdd1243dSDimitry Andric       CPU = "rocketlake";
780bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
781bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ROCKETLAKE;
782bdd1243dSDimitry Andric       break;
783bdd1243dSDimitry Andric 
784bdd1243dSDimitry Andric     // Skylake Xeon:
785bdd1243dSDimitry Andric     case 0x55:
786bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
787bdd1243dSDimitry Andric       if (testFeature(X86::FEATURE_AVX512BF16)) {
788bdd1243dSDimitry Andric         CPU = "cooperlake";
789bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_COOPERLAKE;
790bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
791bdd1243dSDimitry Andric         CPU = "cascadelake";
792bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_CASCADELAKE;
793bdd1243dSDimitry Andric       } else {
794bdd1243dSDimitry Andric         CPU = "skylake-avx512";
795bdd1243dSDimitry Andric         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
796bdd1243dSDimitry Andric       }
797bdd1243dSDimitry Andric       break;
798bdd1243dSDimitry Andric 
799bdd1243dSDimitry Andric     // Cannonlake:
800bdd1243dSDimitry Andric     case 0x66:
801bdd1243dSDimitry Andric       CPU = "cannonlake";
802bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
803bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_CANNONLAKE;
804bdd1243dSDimitry Andric       break;
805bdd1243dSDimitry Andric 
806bdd1243dSDimitry Andric     // Icelake:
807bdd1243dSDimitry Andric     case 0x7d:
808bdd1243dSDimitry Andric     case 0x7e:
809bdd1243dSDimitry Andric       CPU = "icelake-client";
810bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
811bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
812bdd1243dSDimitry Andric       break;
813bdd1243dSDimitry Andric 
814bdd1243dSDimitry Andric     // Tigerlake:
815bdd1243dSDimitry Andric     case 0x8c:
816bdd1243dSDimitry Andric     case 0x8d:
817bdd1243dSDimitry Andric       CPU = "tigerlake";
818bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
819bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_TIGERLAKE;
820bdd1243dSDimitry Andric       break;
821bdd1243dSDimitry Andric 
822bdd1243dSDimitry Andric     // Alderlake:
823bdd1243dSDimitry Andric     case 0x97:
824bdd1243dSDimitry Andric     case 0x9a:
825bdd1243dSDimitry Andric     // Raptorlake:
826bdd1243dSDimitry Andric     case 0xb7:
827bdd1243dSDimitry Andric     // Meteorlake:
828bdd1243dSDimitry Andric     case 0xaa:
829bdd1243dSDimitry Andric     case 0xac:
830bdd1243dSDimitry Andric       CPU = "alderlake";
831bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
832bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
833bdd1243dSDimitry Andric       break;
834bdd1243dSDimitry Andric 
835bdd1243dSDimitry Andric     // Graniterapids:
836bdd1243dSDimitry Andric     case 0xad:
837bdd1243dSDimitry Andric       CPU = "graniterapids";
838bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
839bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS;
840bdd1243dSDimitry Andric       break;
841bdd1243dSDimitry Andric 
84206c3fb27SDimitry Andric     // Granite Rapids D:
84306c3fb27SDimitry Andric     case 0xae:
84406c3fb27SDimitry Andric       CPU = "graniterapids-d";
84506c3fb27SDimitry Andric       *Type = X86::INTEL_COREI7;
84606c3fb27SDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;
84706c3fb27SDimitry Andric       break;
84806c3fb27SDimitry Andric 
849bdd1243dSDimitry Andric     // Icelake Xeon:
850bdd1243dSDimitry Andric     case 0x6a:
851bdd1243dSDimitry Andric     case 0x6c:
852bdd1243dSDimitry Andric       CPU = "icelake-server";
853bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
854bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;
855bdd1243dSDimitry Andric       break;
856bdd1243dSDimitry Andric 
857bdd1243dSDimitry Andric     // Emerald Rapids:
858bdd1243dSDimitry Andric     case 0xcf:
859bdd1243dSDimitry Andric     // Sapphire Rapids:
860bdd1243dSDimitry Andric     case 0x8f:
861bdd1243dSDimitry Andric       CPU = "sapphirerapids";
862bdd1243dSDimitry Andric       *Type = X86::INTEL_COREI7;
863bdd1243dSDimitry Andric       *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;
864bdd1243dSDimitry Andric       break;
865bdd1243dSDimitry Andric 
866bdd1243dSDimitry Andric     case 0x1c: // Most 45 nm Intel Atom processors
867bdd1243dSDimitry Andric     case 0x26: // 45 nm Atom Lincroft
868bdd1243dSDimitry Andric     case 0x27: // 32 nm Atom Medfield
869bdd1243dSDimitry Andric     case 0x35: // 32 nm Atom Midview
870bdd1243dSDimitry Andric     case 0x36: // 32 nm Atom Midview
871bdd1243dSDimitry Andric       CPU = "bonnell";
872bdd1243dSDimitry Andric       *Type = X86::INTEL_BONNELL;
873bdd1243dSDimitry Andric       break;
874bdd1243dSDimitry Andric 
875bdd1243dSDimitry Andric     // Atom Silvermont codes from the Intel software optimization guide.
876bdd1243dSDimitry Andric     case 0x37:
877bdd1243dSDimitry Andric     case 0x4a:
878bdd1243dSDimitry Andric     case 0x4d:
879bdd1243dSDimitry Andric     case 0x5a:
880bdd1243dSDimitry Andric     case 0x5d:
881bdd1243dSDimitry Andric     case 0x4c: // really airmont
882bdd1243dSDimitry Andric       CPU = "silvermont";
883bdd1243dSDimitry Andric       *Type = X86::INTEL_SILVERMONT;
884bdd1243dSDimitry Andric       break;
885bdd1243dSDimitry Andric     // Goldmont:
886bdd1243dSDimitry Andric     case 0x5c: // Apollo Lake
887bdd1243dSDimitry Andric     case 0x5f: // Denverton
888bdd1243dSDimitry Andric       CPU = "goldmont";
889bdd1243dSDimitry Andric       *Type = X86::INTEL_GOLDMONT;
890bdd1243dSDimitry Andric       break;
891bdd1243dSDimitry Andric     case 0x7a:
892bdd1243dSDimitry Andric       CPU = "goldmont-plus";
893bdd1243dSDimitry Andric       *Type = X86::INTEL_GOLDMONT_PLUS;
894bdd1243dSDimitry Andric       break;
895bdd1243dSDimitry Andric     case 0x86:
896bdd1243dSDimitry Andric       CPU = "tremont";
897bdd1243dSDimitry Andric       *Type = X86::INTEL_TREMONT;
898bdd1243dSDimitry Andric       break;
899bdd1243dSDimitry Andric 
900bdd1243dSDimitry Andric     // Sierraforest:
901bdd1243dSDimitry Andric     case 0xaf:
902bdd1243dSDimitry Andric       CPU = "sierraforest";
903bdd1243dSDimitry Andric       *Type = X86::INTEL_SIERRAFOREST;
904bdd1243dSDimitry Andric       break;
905bdd1243dSDimitry Andric 
906bdd1243dSDimitry Andric     // Grandridge:
907bdd1243dSDimitry Andric     case 0xb6:
908bdd1243dSDimitry Andric       CPU = "grandridge";
909bdd1243dSDimitry Andric       *Type = X86::INTEL_GRANDRIDGE;
910bdd1243dSDimitry Andric       break;
911bdd1243dSDimitry Andric 
912bdd1243dSDimitry Andric     // Xeon Phi (Knights Landing + Knights Mill):
913bdd1243dSDimitry Andric     case 0x57:
914bdd1243dSDimitry Andric       CPU = "knl";
915bdd1243dSDimitry Andric       *Type = X86::INTEL_KNL;
916bdd1243dSDimitry Andric       break;
917bdd1243dSDimitry Andric     case 0x85:
918bdd1243dSDimitry Andric       CPU = "knm";
919bdd1243dSDimitry Andric       *Type = X86::INTEL_KNM;
920bdd1243dSDimitry Andric       break;
921bdd1243dSDimitry Andric 
922bdd1243dSDimitry Andric     default: // Unknown family 6 CPU, try to guess.
923bdd1243dSDimitry Andric       // Don't both with Type/Subtype here, they aren't used by the caller.
924bdd1243dSDimitry Andric       // They're used above to keep the code in sync with compiler-rt.
925bdd1243dSDimitry Andric       // TODO detect tigerlake host from model
926bdd1243dSDimitry Andric       if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {
927bdd1243dSDimitry Andric         CPU = "tigerlake";
928bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI2)) {
929bdd1243dSDimitry Andric         CPU = "icelake-client";
930bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI)) {
931bdd1243dSDimitry Andric         CPU = "cannonlake";
932bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512BF16)) {
933bdd1243dSDimitry Andric         CPU = "cooperlake";
934bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
935bdd1243dSDimitry Andric         CPU = "cascadelake";
936bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VL)) {
937bdd1243dSDimitry Andric         CPU = "skylake-avx512";
938bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512ER)) {
939bdd1243dSDimitry Andric         CPU = "knl";
940bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {
941bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_SHA))
942bdd1243dSDimitry Andric           CPU = "goldmont";
943bdd1243dSDimitry Andric         else
944bdd1243dSDimitry Andric           CPU = "skylake";
945bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_ADX)) {
946bdd1243dSDimitry Andric         CPU = "broadwell";
947bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX2)) {
948bdd1243dSDimitry Andric         CPU = "haswell";
949bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_AVX)) {
950bdd1243dSDimitry Andric         CPU = "sandybridge";
951bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_2)) {
952bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
953bdd1243dSDimitry Andric           CPU = "silvermont";
954bdd1243dSDimitry Andric         else
955bdd1243dSDimitry Andric           CPU = "nehalem";
956bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_1)) {
957bdd1243dSDimitry Andric         CPU = "penryn";
958bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSSE3)) {
959bdd1243dSDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
960bdd1243dSDimitry Andric           CPU = "bonnell";
961bdd1243dSDimitry Andric         else
962bdd1243dSDimitry Andric           CPU = "core2";
963bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_64BIT)) {
964bdd1243dSDimitry Andric         CPU = "core2";
965bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE3)) {
966bdd1243dSDimitry Andric         CPU = "yonah";
967bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE2)) {
968bdd1243dSDimitry Andric         CPU = "pentium-m";
969bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_SSE)) {
970bdd1243dSDimitry Andric         CPU = "pentium3";
971bdd1243dSDimitry Andric       } else if (testFeature(X86::FEATURE_MMX)) {
972bdd1243dSDimitry Andric         CPU = "pentium2";
973bdd1243dSDimitry Andric       } else {
974bdd1243dSDimitry Andric         CPU = "pentiumpro";
975bdd1243dSDimitry Andric       }
976bdd1243dSDimitry Andric       break;
977bdd1243dSDimitry Andric     }
978bdd1243dSDimitry Andric     break;
979bdd1243dSDimitry Andric   case 15: {
980bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_64BIT)) {
981bdd1243dSDimitry Andric       CPU = "nocona";
982bdd1243dSDimitry Andric       break;
983bdd1243dSDimitry Andric     }
984bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
985bdd1243dSDimitry Andric       CPU = "prescott";
986bdd1243dSDimitry Andric       break;
987bdd1243dSDimitry Andric     }
988bdd1243dSDimitry Andric     CPU = "pentium4";
989bdd1243dSDimitry Andric     break;
990bdd1243dSDimitry Andric   }
991bdd1243dSDimitry Andric   default:
992bdd1243dSDimitry Andric     break; // Unknown.
993bdd1243dSDimitry Andric   }
994bdd1243dSDimitry Andric 
995bdd1243dSDimitry Andric   return CPU;
996bdd1243dSDimitry Andric }
997bdd1243dSDimitry Andric 
998bdd1243dSDimitry Andric static StringRef
999bdd1243dSDimitry Andric getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
1000bdd1243dSDimitry Andric                               const unsigned *Features,
1001bdd1243dSDimitry Andric                               unsigned *Type, unsigned *Subtype) {
1002bdd1243dSDimitry Andric   auto testFeature = [&](unsigned F) {
1003bdd1243dSDimitry Andric     return (Features[F / 32] & (1U << (F % 32))) != 0;
1004bdd1243dSDimitry Andric   };
1005bdd1243dSDimitry Andric 
1006bdd1243dSDimitry Andric   StringRef CPU;
1007bdd1243dSDimitry Andric 
1008bdd1243dSDimitry Andric   switch (Family) {
1009bdd1243dSDimitry Andric   case 4:
1010bdd1243dSDimitry Andric     CPU = "i486";
1011bdd1243dSDimitry Andric     break;
1012bdd1243dSDimitry Andric   case 5:
1013bdd1243dSDimitry Andric     CPU = "pentium";
1014bdd1243dSDimitry Andric     switch (Model) {
1015bdd1243dSDimitry Andric     case 6:
1016bdd1243dSDimitry Andric     case 7:
1017bdd1243dSDimitry Andric       CPU = "k6";
1018bdd1243dSDimitry Andric       break;
1019bdd1243dSDimitry Andric     case 8:
1020bdd1243dSDimitry Andric       CPU = "k6-2";
1021bdd1243dSDimitry Andric       break;
1022bdd1243dSDimitry Andric     case 9:
1023bdd1243dSDimitry Andric     case 13:
1024bdd1243dSDimitry Andric       CPU = "k6-3";
1025bdd1243dSDimitry Andric       break;
1026bdd1243dSDimitry Andric     case 10:
1027bdd1243dSDimitry Andric       CPU = "geode";
1028bdd1243dSDimitry Andric       break;
1029bdd1243dSDimitry Andric     }
1030bdd1243dSDimitry Andric     break;
1031bdd1243dSDimitry Andric   case 6:
1032bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE)) {
1033bdd1243dSDimitry Andric       CPU = "athlon-xp";
1034bdd1243dSDimitry Andric       break;
1035bdd1243dSDimitry Andric     }
1036bdd1243dSDimitry Andric     CPU = "athlon";
1037bdd1243dSDimitry Andric     break;
1038bdd1243dSDimitry Andric   case 15:
1039bdd1243dSDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
1040bdd1243dSDimitry Andric       CPU = "k8-sse3";
1041bdd1243dSDimitry Andric       break;
1042bdd1243dSDimitry Andric     }
1043bdd1243dSDimitry Andric     CPU = "k8";
1044bdd1243dSDimitry Andric     break;
1045bdd1243dSDimitry Andric   case 16:
1046bdd1243dSDimitry Andric     CPU = "amdfam10";
1047bdd1243dSDimitry Andric     *Type = X86::AMDFAM10H; // "amdfam10"
1048bdd1243dSDimitry Andric     switch (Model) {
1049bdd1243dSDimitry Andric     case 2:
1050bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_BARCELONA;
1051bdd1243dSDimitry Andric       break;
1052bdd1243dSDimitry Andric     case 4:
1053bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_SHANGHAI;
1054bdd1243dSDimitry Andric       break;
1055bdd1243dSDimitry Andric     case 8:
1056bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM10H_ISTANBUL;
1057bdd1243dSDimitry Andric       break;
1058bdd1243dSDimitry Andric     }
1059bdd1243dSDimitry Andric     break;
1060bdd1243dSDimitry Andric   case 20:
1061bdd1243dSDimitry Andric     CPU = "btver1";
1062bdd1243dSDimitry Andric     *Type = X86::AMD_BTVER1;
1063bdd1243dSDimitry Andric     break;
1064bdd1243dSDimitry Andric   case 21:
1065bdd1243dSDimitry Andric     CPU = "bdver1";
1066bdd1243dSDimitry Andric     *Type = X86::AMDFAM15H;
1067bdd1243dSDimitry Andric     if (Model >= 0x60 && Model <= 0x7f) {
1068bdd1243dSDimitry Andric       CPU = "bdver4";
1069bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER4;
1070bdd1243dSDimitry Andric       break; // 60h-7Fh: Excavator
1071bdd1243dSDimitry Andric     }
1072bdd1243dSDimitry Andric     if (Model >= 0x30 && Model <= 0x3f) {
1073bdd1243dSDimitry Andric       CPU = "bdver3";
1074bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER3;
1075bdd1243dSDimitry Andric       break; // 30h-3Fh: Steamroller
1076bdd1243dSDimitry Andric     }
1077bdd1243dSDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
1078bdd1243dSDimitry Andric       CPU = "bdver2";
1079bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER2;
1080bdd1243dSDimitry Andric       break; // 02h, 10h-1Fh: Piledriver
1081bdd1243dSDimitry Andric     }
1082bdd1243dSDimitry Andric     if (Model <= 0x0f) {
1083bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER1;
1084bdd1243dSDimitry Andric       break; // 00h-0Fh: Bulldozer
1085bdd1243dSDimitry Andric     }
1086bdd1243dSDimitry Andric     break;
1087bdd1243dSDimitry Andric   case 22:
1088bdd1243dSDimitry Andric     CPU = "btver2";
1089bdd1243dSDimitry Andric     *Type = X86::AMD_BTVER2;
1090bdd1243dSDimitry Andric     break;
1091bdd1243dSDimitry Andric   case 23:
1092bdd1243dSDimitry Andric     CPU = "znver1";
1093bdd1243dSDimitry Andric     *Type = X86::AMDFAM17H;
1094bdd1243dSDimitry Andric     if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) {
1095bdd1243dSDimitry Andric       CPU = "znver2";
1096bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER2;
1097bdd1243dSDimitry Andric       break; // 30h-3fh, 71h: Zen2
1098bdd1243dSDimitry Andric     }
1099bdd1243dSDimitry Andric     if (Model <= 0x0f) {
1100bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER1;
1101bdd1243dSDimitry Andric       break; // 00h-0Fh: Zen1
1102bdd1243dSDimitry Andric     }
1103bdd1243dSDimitry Andric     break;
1104bdd1243dSDimitry Andric   case 25:
1105bdd1243dSDimitry Andric     CPU = "znver3";
1106bdd1243dSDimitry Andric     *Type = X86::AMDFAM19H;
1107bdd1243dSDimitry Andric     if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x5f)) {
1108bdd1243dSDimitry Andric       // Family 19h Models 00h-0Fh - Zen3
1109bdd1243dSDimitry Andric       // Family 19h Models 20h-2Fh - Zen3
1110bdd1243dSDimitry Andric       // Family 19h Models 30h-3Fh - Zen3
1111bdd1243dSDimitry Andric       // Family 19h Models 40h-4Fh - Zen3+
1112bdd1243dSDimitry Andric       // Family 19h Models 50h-5Fh - Zen3+
1113bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER3;
1114bdd1243dSDimitry Andric       break;
1115bdd1243dSDimitry Andric     }
1116bdd1243dSDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) ||
1117bdd1243dSDimitry Andric         (Model >= 0x60 && Model <= 0x74) ||
1118bdd1243dSDimitry Andric         (Model >= 0x78 && Model <= 0x7b) ||
1119bdd1243dSDimitry Andric         (Model >= 0xA0 && Model <= 0xAf)) {
1120bdd1243dSDimitry Andric       CPU = "znver4";
1121bdd1243dSDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER4;
1122bdd1243dSDimitry Andric       break; //  "znver4"
1123bdd1243dSDimitry Andric     }
1124bdd1243dSDimitry Andric     break; // family 19h
1125bdd1243dSDimitry Andric   default:
1126bdd1243dSDimitry Andric     break; // Unknown AMD CPU.
1127bdd1243dSDimitry Andric   }
1128bdd1243dSDimitry Andric 
1129bdd1243dSDimitry Andric   return CPU;
1130bdd1243dSDimitry Andric }
1131bdd1243dSDimitry Andric 
1132bdd1243dSDimitry Andric static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
1133bdd1243dSDimitry Andric                                  unsigned *Features) {
1134bdd1243dSDimitry Andric   unsigned EAX, EBX;
1135bdd1243dSDimitry Andric 
1136bdd1243dSDimitry Andric   auto setFeature = [&](unsigned F) {
1137bdd1243dSDimitry Andric     Features[F / 32] |= 1U << (F % 32);
1138bdd1243dSDimitry Andric   };
1139bdd1243dSDimitry Andric 
1140bdd1243dSDimitry Andric   if ((EDX >> 15) & 1)
1141bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CMOV);
1142bdd1243dSDimitry Andric   if ((EDX >> 23) & 1)
1143bdd1243dSDimitry Andric     setFeature(X86::FEATURE_MMX);
1144bdd1243dSDimitry Andric   if ((EDX >> 25) & 1)
1145bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE);
1146bdd1243dSDimitry Andric   if ((EDX >> 26) & 1)
1147bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE2);
1148bdd1243dSDimitry Andric 
1149bdd1243dSDimitry Andric   if ((ECX >> 0) & 1)
1150bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE3);
1151bdd1243dSDimitry Andric   if ((ECX >> 1) & 1)
1152bdd1243dSDimitry Andric     setFeature(X86::FEATURE_PCLMUL);
1153bdd1243dSDimitry Andric   if ((ECX >> 9) & 1)
1154bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSSE3);
1155bdd1243dSDimitry Andric   if ((ECX >> 12) & 1)
1156bdd1243dSDimitry Andric     setFeature(X86::FEATURE_FMA);
1157bdd1243dSDimitry Andric   if ((ECX >> 19) & 1)
1158bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_1);
1159bdd1243dSDimitry Andric   if ((ECX >> 20) & 1) {
1160bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_2);
1161bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CRC32);
1162bdd1243dSDimitry Andric   }
1163bdd1243dSDimitry Andric   if ((ECX >> 23) & 1)
1164bdd1243dSDimitry Andric     setFeature(X86::FEATURE_POPCNT);
1165bdd1243dSDimitry Andric   if ((ECX >> 25) & 1)
1166bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AES);
1167bdd1243dSDimitry Andric 
1168bdd1243dSDimitry Andric   if ((ECX >> 22) & 1)
1169bdd1243dSDimitry Andric     setFeature(X86::FEATURE_MOVBE);
1170bdd1243dSDimitry Andric 
1171bdd1243dSDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1172bdd1243dSDimitry Andric   // indicates that the AVX registers will be saved and restored on context
1173bdd1243dSDimitry Andric   // switch, then we have full AVX support.
1174bdd1243dSDimitry Andric   const unsigned AVXBits = (1 << 27) | (1 << 28);
1175bdd1243dSDimitry Andric   bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
1176bdd1243dSDimitry Andric                 ((EAX & 0x6) == 0x6);
1177bdd1243dSDimitry Andric #if defined(__APPLE__)
1178bdd1243dSDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1179bdd1243dSDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1180bdd1243dSDimitry Andric   // set right now.
1181bdd1243dSDimitry Andric   bool HasAVX512Save = true;
1182bdd1243dSDimitry Andric #else
1183bdd1243dSDimitry Andric   // AVX512 requires additional context to be saved by the OS.
1184bdd1243dSDimitry Andric   bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
1185bdd1243dSDimitry Andric #endif
1186bdd1243dSDimitry Andric 
1187bdd1243dSDimitry Andric   if (HasAVX)
1188bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX);
1189bdd1243dSDimitry Andric 
1190bdd1243dSDimitry Andric   bool HasLeaf7 =
1191bdd1243dSDimitry Andric       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1192bdd1243dSDimitry Andric 
1193bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 3) & 1))
1194bdd1243dSDimitry Andric     setFeature(X86::FEATURE_BMI);
1195bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
1196bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX2);
1197bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 8) & 1))
1198bdd1243dSDimitry Andric     setFeature(X86::FEATURE_BMI2);
1199bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
1200bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512F);
1201bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
1202bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512DQ);
1203bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 19) & 1))
1204bdd1243dSDimitry Andric     setFeature(X86::FEATURE_ADX);
1205bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
1206bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512IFMA);
1207bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 23) & 1))
1208bdd1243dSDimitry Andric     setFeature(X86::FEATURE_CLFLUSHOPT);
1209bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
1210bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512PF);
1211bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
1212bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512ER);
1213bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
1214bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512CD);
1215bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 29) & 1))
1216bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SHA);
1217bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
1218bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BW);
1219bdd1243dSDimitry Andric   if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
1220bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VL);
1221bdd1243dSDimitry Andric 
1222bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
1223bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI);
1224bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
1225bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI2);
1226bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 8) & 1))
1227bdd1243dSDimitry Andric     setFeature(X86::FEATURE_GFNI);
1228bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
1229bdd1243dSDimitry Andric     setFeature(X86::FEATURE_VPCLMULQDQ);
1230bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
1231bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VNNI);
1232bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
1233bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BITALG);
1234bdd1243dSDimitry Andric   if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
1235bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
1236bdd1243dSDimitry Andric 
1237bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
1238bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX5124VNNIW);
1239bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
1240bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX5124FMAPS);
1241bdd1243dSDimitry Andric   if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
1242bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512VP2INTERSECT);
1243bdd1243dSDimitry Andric 
1244*8a4dda33SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
1245*8a4dda33SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
1246bdd1243dSDimitry Andric   bool HasLeaf7Subleaf1 =
1247*8a4dda33SDimitry Andric       HasLeaf7 && EAX >= 1 &&
1248*8a4dda33SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1249bdd1243dSDimitry Andric   if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
1250bdd1243dSDimitry Andric     setFeature(X86::FEATURE_AVX512BF16);
1251bdd1243dSDimitry Andric 
1252bdd1243dSDimitry Andric   unsigned MaxExtLevel;
1253bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1254bdd1243dSDimitry Andric 
1255bdd1243dSDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1256bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1257bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 6) & 1))
1258bdd1243dSDimitry Andric     setFeature(X86::FEATURE_SSE4_A);
1259bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 11) & 1))
1260bdd1243dSDimitry Andric     setFeature(X86::FEATURE_XOP);
1261bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((ECX >> 16) & 1))
1262bdd1243dSDimitry Andric     setFeature(X86::FEATURE_FMA4);
1263bdd1243dSDimitry Andric 
1264bdd1243dSDimitry Andric   if (HasExtLeaf1 && ((EDX >> 29) & 1))
1265bdd1243dSDimitry Andric     setFeature(X86::FEATURE_64BIT);
1266bdd1243dSDimitry Andric }
1267bdd1243dSDimitry Andric 
1268bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1269bdd1243dSDimitry Andric   unsigned MaxLeaf = 0;
1270bdd1243dSDimitry Andric   const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);
1271bdd1243dSDimitry Andric   if (Vendor == VendorSignatures::UNKNOWN)
1272bdd1243dSDimitry Andric     return "generic";
1273bdd1243dSDimitry Andric 
1274bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1275bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
1276bdd1243dSDimitry Andric 
1277bdd1243dSDimitry Andric   unsigned Family = 0, Model = 0;
1278bdd1243dSDimitry Andric   unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};
1279bdd1243dSDimitry Andric   detectX86FamilyModel(EAX, &Family, &Model);
1280bdd1243dSDimitry Andric   getAvailableFeatures(ECX, EDX, MaxLeaf, Features);
1281bdd1243dSDimitry Andric 
1282bdd1243dSDimitry Andric   // These aren't consumed in this file, but we try to keep some source code the
1283bdd1243dSDimitry Andric   // same or similar to compiler-rt.
1284bdd1243dSDimitry Andric   unsigned Type = 0;
1285bdd1243dSDimitry Andric   unsigned Subtype = 0;
1286bdd1243dSDimitry Andric 
1287bdd1243dSDimitry Andric   StringRef CPU;
1288bdd1243dSDimitry Andric 
1289bdd1243dSDimitry Andric   if (Vendor == VendorSignatures::GENUINE_INTEL) {
1290bdd1243dSDimitry Andric     CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,
1291bdd1243dSDimitry Andric                                           &Subtype);
1292bdd1243dSDimitry Andric   } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {
1293bdd1243dSDimitry Andric     CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,
1294bdd1243dSDimitry Andric                                         &Subtype);
1295bdd1243dSDimitry Andric   }
1296bdd1243dSDimitry Andric 
1297bdd1243dSDimitry Andric   if (!CPU.empty())
1298bdd1243dSDimitry Andric     return CPU;
1299bdd1243dSDimitry Andric 
1300bdd1243dSDimitry Andric   return "generic";
1301bdd1243dSDimitry Andric }
1302bdd1243dSDimitry Andric 
1303bdd1243dSDimitry Andric #elif defined(__APPLE__) && defined(__powerpc__)
1304bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1305bdd1243dSDimitry Andric   host_basic_info_data_t hostInfo;
1306bdd1243dSDimitry Andric   mach_msg_type_number_t infoCount;
1307bdd1243dSDimitry Andric 
1308bdd1243dSDimitry Andric   infoCount = HOST_BASIC_INFO_COUNT;
1309bdd1243dSDimitry Andric   mach_port_t hostPort = mach_host_self();
1310bdd1243dSDimitry Andric   host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
1311bdd1243dSDimitry Andric             &infoCount);
1312bdd1243dSDimitry Andric   mach_port_deallocate(mach_task_self(), hostPort);
1313bdd1243dSDimitry Andric 
1314bdd1243dSDimitry Andric   if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
1315bdd1243dSDimitry Andric     return "generic";
1316bdd1243dSDimitry Andric 
1317bdd1243dSDimitry Andric   switch (hostInfo.cpu_subtype) {
1318bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_601:
1319bdd1243dSDimitry Andric     return "601";
1320bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_602:
1321bdd1243dSDimitry Andric     return "602";
1322bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603:
1323bdd1243dSDimitry Andric     return "603";
1324bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603e:
1325bdd1243dSDimitry Andric     return "603e";
1326bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603ev:
1327bdd1243dSDimitry Andric     return "603ev";
1328bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604:
1329bdd1243dSDimitry Andric     return "604";
1330bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604e:
1331bdd1243dSDimitry Andric     return "604e";
1332bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_620:
1333bdd1243dSDimitry Andric     return "620";
1334bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_750:
1335bdd1243dSDimitry Andric     return "750";
1336bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7400:
1337bdd1243dSDimitry Andric     return "7400";
1338bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7450:
1339bdd1243dSDimitry Andric     return "7450";
1340bdd1243dSDimitry Andric   case CPU_SUBTYPE_POWERPC_970:
1341bdd1243dSDimitry Andric     return "970";
1342bdd1243dSDimitry Andric   default:;
1343bdd1243dSDimitry Andric   }
1344bdd1243dSDimitry Andric 
1345bdd1243dSDimitry Andric   return "generic";
1346bdd1243dSDimitry Andric }
1347bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__powerpc__)
1348bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1349bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1350bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1351bdd1243dSDimitry Andric   return detail::getHostCPUNameForPowerPC(Content);
1352bdd1243dSDimitry Andric }
1353bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1354bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1355bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1356bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1357bdd1243dSDimitry Andric   return detail::getHostCPUNameForARM(Content);
1358bdd1243dSDimitry Andric }
1359bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__s390x__)
1360bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1361bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1362bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1363bdd1243dSDimitry Andric   return detail::getHostCPUNameForS390x(Content);
1364bdd1243dSDimitry Andric }
1365bdd1243dSDimitry Andric #elif defined(__MVS__)
1366bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1367bdd1243dSDimitry Andric   // Get pointer to Communications Vector Table (CVT).
1368bdd1243dSDimitry Andric   // The pointer is located at offset 16 of the Prefixed Save Area (PSA).
1369bdd1243dSDimitry Andric   // It is stored as 31 bit pointer and will be zero-extended to 64 bit.
1370bdd1243dSDimitry Andric   int *StartToCVTOffset = reinterpret_cast<int *>(0x10);
1371bdd1243dSDimitry Andric   // Since its stored as a 31-bit pointer, get the 4 bytes from the start
1372bdd1243dSDimitry Andric   // of address.
1373bdd1243dSDimitry Andric   int ReadValue = *StartToCVTOffset;
1374bdd1243dSDimitry Andric   // Explicitly clear the high order bit.
1375bdd1243dSDimitry Andric   ReadValue = (ReadValue & 0x7FFFFFFF);
1376bdd1243dSDimitry Andric   char *CVT = reinterpret_cast<char *>(ReadValue);
1377bdd1243dSDimitry Andric   // The model number is located in the CVT prefix at offset -6 and stored as
1378bdd1243dSDimitry Andric   // signless packed decimal.
1379bdd1243dSDimitry Andric   uint16_t Id = *(uint16_t *)&CVT[-6];
1380bdd1243dSDimitry Andric   // Convert number to integer.
1381bdd1243dSDimitry Andric   Id = decodePackedBCD<uint16_t>(Id, false);
1382bdd1243dSDimitry Andric   // Check for vector support. It's stored in field CVTFLAG5 (offset 244),
1383bdd1243dSDimitry Andric   // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector
1384bdd1243dSDimitry Andric   // extension can only be used if bit CVTVEF is on.
1385bdd1243dSDimitry Andric   bool HaveVectorSupport = CVT[244] & 0x80;
1386bdd1243dSDimitry Andric   return getCPUNameFromS390Model(Id, HaveVectorSupport);
1387bdd1243dSDimitry Andric }
1388bdd1243dSDimitry Andric #elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
1389bdd1243dSDimitry Andric #define CPUFAMILY_ARM_SWIFT 0x1e2d6381
1390bdd1243dSDimitry Andric #define CPUFAMILY_ARM_CYCLONE 0x37a09642
1391bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
1392bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TWISTER 0x92fb37c8
1393bdd1243dSDimitry Andric #define CPUFAMILY_ARM_HURRICANE 0x67ceee93
1394bdd1243dSDimitry Andric #define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
1395bdd1243dSDimitry Andric #define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
1396bdd1243dSDimitry Andric #define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
1397bdd1243dSDimitry Andric #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
1398bdd1243dSDimitry Andric 
1399bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1400bdd1243dSDimitry Andric   uint32_t Family;
1401bdd1243dSDimitry Andric   size_t Length = sizeof(Family);
1402bdd1243dSDimitry Andric   sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);
1403bdd1243dSDimitry Andric 
1404bdd1243dSDimitry Andric   switch (Family) {
1405bdd1243dSDimitry Andric   case CPUFAMILY_ARM_SWIFT:
1406bdd1243dSDimitry Andric     return "swift";
1407bdd1243dSDimitry Andric   case CPUFAMILY_ARM_CYCLONE:
1408bdd1243dSDimitry Andric     return "apple-a7";
1409bdd1243dSDimitry Andric   case CPUFAMILY_ARM_TYPHOON:
1410bdd1243dSDimitry Andric     return "apple-a8";
1411bdd1243dSDimitry Andric   case CPUFAMILY_ARM_TWISTER:
1412bdd1243dSDimitry Andric     return "apple-a9";
1413bdd1243dSDimitry Andric   case CPUFAMILY_ARM_HURRICANE:
1414bdd1243dSDimitry Andric     return "apple-a10";
1415bdd1243dSDimitry Andric   case CPUFAMILY_ARM_MONSOON_MISTRAL:
1416bdd1243dSDimitry Andric     return "apple-a11";
1417bdd1243dSDimitry Andric   case CPUFAMILY_ARM_VORTEX_TEMPEST:
1418bdd1243dSDimitry Andric     return "apple-a12";
1419bdd1243dSDimitry Andric   case CPUFAMILY_ARM_LIGHTNING_THUNDER:
1420bdd1243dSDimitry Andric     return "apple-a13";
1421bdd1243dSDimitry Andric   case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
1422bdd1243dSDimitry Andric     return "apple-m1";
1423bdd1243dSDimitry Andric   default:
1424bdd1243dSDimitry Andric     // Default to the newest CPU we know about.
1425bdd1243dSDimitry Andric     return "apple-m1";
1426bdd1243dSDimitry Andric   }
1427bdd1243dSDimitry Andric }
1428bdd1243dSDimitry Andric #elif defined(_AIX)
1429bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1430bdd1243dSDimitry Andric   switch (_system_configuration.implementation) {
1431bdd1243dSDimitry Andric   case POWER_4:
1432bdd1243dSDimitry Andric     if (_system_configuration.version == PV_4_3)
1433bdd1243dSDimitry Andric       return "970";
1434bdd1243dSDimitry Andric     return "pwr4";
1435bdd1243dSDimitry Andric   case POWER_5:
1436bdd1243dSDimitry Andric     if (_system_configuration.version == PV_5)
1437bdd1243dSDimitry Andric       return "pwr5";
1438bdd1243dSDimitry Andric     return "pwr5x";
1439bdd1243dSDimitry Andric   case POWER_6:
1440bdd1243dSDimitry Andric     if (_system_configuration.version == PV_6_Compat)
1441bdd1243dSDimitry Andric       return "pwr6";
1442bdd1243dSDimitry Andric     return "pwr6x";
1443bdd1243dSDimitry Andric   case POWER_7:
1444bdd1243dSDimitry Andric     return "pwr7";
1445bdd1243dSDimitry Andric   case POWER_8:
1446bdd1243dSDimitry Andric     return "pwr8";
1447bdd1243dSDimitry Andric   case POWER_9:
1448bdd1243dSDimitry Andric     return "pwr9";
1449bdd1243dSDimitry Andric // TODO: simplify this once the macro is available in all OS levels.
1450bdd1243dSDimitry Andric #ifdef POWER_10
1451bdd1243dSDimitry Andric   case POWER_10:
1452bdd1243dSDimitry Andric #else
1453bdd1243dSDimitry Andric   case 0x40000:
1454bdd1243dSDimitry Andric #endif
1455bdd1243dSDimitry Andric     return "pwr10";
1456bdd1243dSDimitry Andric   default:
1457bdd1243dSDimitry Andric     return "generic";
1458bdd1243dSDimitry Andric   }
1459bdd1243dSDimitry Andric }
146006c3fb27SDimitry Andric #elif defined(__loongarch__)
146106c3fb27SDimitry Andric StringRef sys::getHostCPUName() {
146206c3fb27SDimitry Andric   // Use processor id to detect cpu name.
146306c3fb27SDimitry Andric   uint32_t processor_id;
146406c3fb27SDimitry Andric   __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));
146506c3fb27SDimitry Andric   switch (processor_id & 0xff00) {
146606c3fb27SDimitry Andric   case 0xc000: // Loongson 64bit, 4-issue
146706c3fb27SDimitry Andric     return "la464";
146806c3fb27SDimitry Andric   // TODO: Others.
146906c3fb27SDimitry Andric   default:
147006c3fb27SDimitry Andric     break;
147106c3fb27SDimitry Andric   }
147206c3fb27SDimitry Andric   return "generic";
147306c3fb27SDimitry Andric }
1474bdd1243dSDimitry Andric #elif defined(__riscv)
1475bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1476bdd1243dSDimitry Andric #if defined(__linux__)
1477bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1478bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1479bdd1243dSDimitry Andric   return detail::getHostCPUNameForRISCV(Content);
1480bdd1243dSDimitry Andric #else
1481bdd1243dSDimitry Andric #if __riscv_xlen == 64
1482bdd1243dSDimitry Andric   return "generic-rv64";
1483bdd1243dSDimitry Andric #elif __riscv_xlen == 32
1484bdd1243dSDimitry Andric   return "generic-rv32";
1485bdd1243dSDimitry Andric #else
1486bdd1243dSDimitry Andric #error "Unhandled value of __riscv_xlen"
1487bdd1243dSDimitry Andric #endif
1488bdd1243dSDimitry Andric #endif
1489bdd1243dSDimitry Andric }
1490bdd1243dSDimitry Andric #elif defined(__sparc__)
1491bdd1243dSDimitry Andric #if defined(__linux__)
1492bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {
1493bdd1243dSDimitry Andric   SmallVector<StringRef> Lines;
1494bdd1243dSDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
1495bdd1243dSDimitry Andric 
1496bdd1243dSDimitry Andric   // Look for cpu line to determine cpu name
1497bdd1243dSDimitry Andric   StringRef Cpu;
1498bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
1499bdd1243dSDimitry Andric     if (Lines[I].startswith("cpu")) {
1500bdd1243dSDimitry Andric       Cpu = Lines[I].substr(5).ltrim("\t :");
1501bdd1243dSDimitry Andric       break;
1502bdd1243dSDimitry Andric     }
1503bdd1243dSDimitry Andric   }
1504bdd1243dSDimitry Andric 
1505bdd1243dSDimitry Andric   return StringSwitch<const char *>(Cpu)
1506bdd1243dSDimitry Andric       .StartsWith("SuperSparc", "supersparc")
1507bdd1243dSDimitry Andric       .StartsWith("HyperSparc", "hypersparc")
1508bdd1243dSDimitry Andric       .StartsWith("SpitFire", "ultrasparc")
1509bdd1243dSDimitry Andric       .StartsWith("BlackBird", "ultrasparc")
1510bdd1243dSDimitry Andric       .StartsWith("Sabre", " ultrasparc")
1511bdd1243dSDimitry Andric       .StartsWith("Hummingbird", "ultrasparc")
1512bdd1243dSDimitry Andric       .StartsWith("Cheetah", "ultrasparc3")
1513bdd1243dSDimitry Andric       .StartsWith("Jalapeno", "ultrasparc3")
1514bdd1243dSDimitry Andric       .StartsWith("Jaguar", "ultrasparc3")
1515bdd1243dSDimitry Andric       .StartsWith("Panther", "ultrasparc3")
1516bdd1243dSDimitry Andric       .StartsWith("Serrano", "ultrasparc3")
1517bdd1243dSDimitry Andric       .StartsWith("UltraSparc T1", "niagara")
1518bdd1243dSDimitry Andric       .StartsWith("UltraSparc T2", "niagara2")
1519bdd1243dSDimitry Andric       .StartsWith("UltraSparc T3", "niagara3")
1520bdd1243dSDimitry Andric       .StartsWith("UltraSparc T4", "niagara4")
1521bdd1243dSDimitry Andric       .StartsWith("UltraSparc T5", "niagara4")
1522bdd1243dSDimitry Andric       .StartsWith("LEON", "leon3")
1523bdd1243dSDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1524bdd1243dSDimitry Andric       .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)
1525bdd1243dSDimitry Andric       .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)
1526bdd1243dSDimitry Andric       .StartsWith("SPARC-M8", "niagara4" /* "m8" */)
1527bdd1243dSDimitry Andric       .Default("generic");
1528bdd1243dSDimitry Andric }
1529bdd1243dSDimitry Andric #endif
1530bdd1243dSDimitry Andric 
1531bdd1243dSDimitry Andric StringRef sys::getHostCPUName() {
1532bdd1243dSDimitry Andric #if defined(__linux__)
1533bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1534bdd1243dSDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1535bdd1243dSDimitry Andric   return detail::getHostCPUNameForSPARC(Content);
1536bdd1243dSDimitry Andric #elif defined(__sun__) && defined(__svr4__)
1537bdd1243dSDimitry Andric   char *buf = NULL;
1538bdd1243dSDimitry Andric   kstat_ctl_t *kc;
1539bdd1243dSDimitry Andric   kstat_t *ksp;
1540bdd1243dSDimitry Andric   kstat_named_t *brand = NULL;
1541bdd1243dSDimitry Andric 
1542bdd1243dSDimitry Andric   kc = kstat_open();
1543bdd1243dSDimitry Andric   if (kc != NULL) {
1544bdd1243dSDimitry Andric     ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);
1545bdd1243dSDimitry Andric     if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&
1546bdd1243dSDimitry Andric         ksp->ks_type == KSTAT_TYPE_NAMED)
1547bdd1243dSDimitry Andric       brand =
1548bdd1243dSDimitry Andric           (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));
1549bdd1243dSDimitry Andric     if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
1550bdd1243dSDimitry Andric       buf = KSTAT_NAMED_STR_PTR(brand);
1551bdd1243dSDimitry Andric   }
1552bdd1243dSDimitry Andric   kstat_close(kc);
1553bdd1243dSDimitry Andric 
1554bdd1243dSDimitry Andric   return StringSwitch<const char *>(buf)
1555bdd1243dSDimitry Andric       .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I
1556bdd1243dSDimitry Andric       .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I
1557bdd1243dSDimitry Andric       .Case("TMS390Z55",
1558bdd1243dSDimitry Andric             "supersparc") // Texas Instruments SuperSPARC I with SuperCache
1559bdd1243dSDimitry Andric       .Case("MB86904", "supersparc") // Fujitsu microSPARC II
1560bdd1243dSDimitry Andric       .Case("MB86907", "supersparc") // Fujitsu TurboSPARC
1561bdd1243dSDimitry Andric       .Case("RT623", "hypersparc")   // Ross hyperSPARC
1562bdd1243dSDimitry Andric       .Case("RT625", "hypersparc")
1563bdd1243dSDimitry Andric       .Case("RT626", "hypersparc")
1564bdd1243dSDimitry Andric       .Case("UltraSPARC-I", "ultrasparc")
1565bdd1243dSDimitry Andric       .Case("UltraSPARC-II", "ultrasparc")
1566bdd1243dSDimitry Andric       .Case("UltraSPARC-IIe", "ultrasparc")
1567bdd1243dSDimitry Andric       .Case("UltraSPARC-IIi", "ultrasparc")
1568bdd1243dSDimitry Andric       .Case("SPARC64-III", "ultrasparc")
1569bdd1243dSDimitry Andric       .Case("SPARC64-IV", "ultrasparc")
1570bdd1243dSDimitry Andric       .Case("UltraSPARC-III", "ultrasparc3")
1571bdd1243dSDimitry Andric       .Case("UltraSPARC-III+", "ultrasparc3")
1572bdd1243dSDimitry Andric       .Case("UltraSPARC-IIIi", "ultrasparc3")
1573bdd1243dSDimitry Andric       .Case("UltraSPARC-IIIi+", "ultrasparc3")
1574bdd1243dSDimitry Andric       .Case("UltraSPARC-IV", "ultrasparc3")
1575bdd1243dSDimitry Andric       .Case("UltraSPARC-IV+", "ultrasparc3")
1576bdd1243dSDimitry Andric       .Case("SPARC64-V", "ultrasparc3")
1577bdd1243dSDimitry Andric       .Case("SPARC64-VI", "ultrasparc3")
1578bdd1243dSDimitry Andric       .Case("SPARC64-VII", "ultrasparc3")
1579bdd1243dSDimitry Andric       .Case("UltraSPARC-T1", "niagara")
1580bdd1243dSDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1581bdd1243dSDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1582bdd1243dSDimitry Andric       .Case("UltraSPARC-T2+", "niagara2")
1583bdd1243dSDimitry Andric       .Case("SPARC-T3", "niagara3")
1584bdd1243dSDimitry Andric       .Case("SPARC-T4", "niagara4")
1585bdd1243dSDimitry Andric       .Case("SPARC-T5", "niagara4")
1586bdd1243dSDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1587bdd1243dSDimitry Andric       .Case("SPARC-M7", "niagara4" /* "niagara7" */)
1588bdd1243dSDimitry Andric       .Case("SPARC-S7", "niagara4" /* "niagara7" */)
1589bdd1243dSDimitry Andric       .Case("SPARC-M8", "niagara4" /* "m8" */)
1590bdd1243dSDimitry Andric       .Default("generic");
1591bdd1243dSDimitry Andric #else
1592bdd1243dSDimitry Andric   return "generic";
1593bdd1243dSDimitry Andric #endif
1594bdd1243dSDimitry Andric }
1595bdd1243dSDimitry Andric #else
1596bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { return "generic"; }
1597bdd1243dSDimitry Andric namespace llvm {
1598bdd1243dSDimitry Andric namespace sys {
1599bdd1243dSDimitry Andric namespace detail {
1600bdd1243dSDimitry Andric namespace x86 {
1601bdd1243dSDimitry Andric 
1602bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
1603bdd1243dSDimitry Andric   return VendorSignatures::UNKNOWN;
1604bdd1243dSDimitry Andric }
1605bdd1243dSDimitry Andric 
1606bdd1243dSDimitry Andric } // namespace x86
1607bdd1243dSDimitry Andric } // namespace detail
1608bdd1243dSDimitry Andric } // namespace sys
1609bdd1243dSDimitry Andric } // namespace llvm
1610bdd1243dSDimitry Andric #endif
1611bdd1243dSDimitry Andric 
1612bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
1613bdd1243dSDimitry Andric     defined(__x86_64__) || defined(_M_X64)
1614bdd1243dSDimitry Andric bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1615bdd1243dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1616bdd1243dSDimitry Andric   unsigned MaxLevel;
1617bdd1243dSDimitry Andric 
1618bdd1243dSDimitry Andric   if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)
1619bdd1243dSDimitry Andric     return false;
1620bdd1243dSDimitry Andric 
1621bdd1243dSDimitry Andric   getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1622bdd1243dSDimitry Andric 
1623bdd1243dSDimitry Andric   Features["cx8"]    = (EDX >>  8) & 1;
1624bdd1243dSDimitry Andric   Features["cmov"]   = (EDX >> 15) & 1;
1625bdd1243dSDimitry Andric   Features["mmx"]    = (EDX >> 23) & 1;
1626bdd1243dSDimitry Andric   Features["fxsr"]   = (EDX >> 24) & 1;
1627bdd1243dSDimitry Andric   Features["sse"]    = (EDX >> 25) & 1;
1628bdd1243dSDimitry Andric   Features["sse2"]   = (EDX >> 26) & 1;
1629bdd1243dSDimitry Andric 
1630bdd1243dSDimitry Andric   Features["sse3"]   = (ECX >>  0) & 1;
1631bdd1243dSDimitry Andric   Features["pclmul"] = (ECX >>  1) & 1;
1632bdd1243dSDimitry Andric   Features["ssse3"]  = (ECX >>  9) & 1;
1633bdd1243dSDimitry Andric   Features["cx16"]   = (ECX >> 13) & 1;
1634bdd1243dSDimitry Andric   Features["sse4.1"] = (ECX >> 19) & 1;
1635bdd1243dSDimitry Andric   Features["sse4.2"] = (ECX >> 20) & 1;
1636bdd1243dSDimitry Andric   Features["crc32"]  = Features["sse4.2"];
1637bdd1243dSDimitry Andric   Features["movbe"]  = (ECX >> 22) & 1;
1638bdd1243dSDimitry Andric   Features["popcnt"] = (ECX >> 23) & 1;
1639bdd1243dSDimitry Andric   Features["aes"]    = (ECX >> 25) & 1;
1640bdd1243dSDimitry Andric   Features["rdrnd"]  = (ECX >> 30) & 1;
1641bdd1243dSDimitry Andric 
1642bdd1243dSDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1643bdd1243dSDimitry Andric   // indicates that the AVX registers will be saved and restored on context
1644bdd1243dSDimitry Andric   // switch, then we have full AVX support.
1645bdd1243dSDimitry Andric   bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
1646bdd1243dSDimitry Andric   bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);
1647bdd1243dSDimitry Andric #if defined(__APPLE__)
1648bdd1243dSDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1649bdd1243dSDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1650bdd1243dSDimitry Andric   // set right now.
1651bdd1243dSDimitry Andric   bool HasAVX512Save = true;
1652bdd1243dSDimitry Andric #else
1653bdd1243dSDimitry Andric   // AVX512 requires additional context to be saved by the OS.
1654bdd1243dSDimitry Andric   bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1655bdd1243dSDimitry Andric #endif
1656bdd1243dSDimitry Andric   // AMX requires additional context to be saved by the OS.
1657bdd1243dSDimitry Andric   const unsigned AMXBits = (1 << 17) | (1 << 18);
1658bdd1243dSDimitry Andric   bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
1659bdd1243dSDimitry Andric 
1660bdd1243dSDimitry Andric   Features["avx"]   = HasAVXSave;
1661bdd1243dSDimitry Andric   Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;
1662bdd1243dSDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1663bdd1243dSDimitry Andric   Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1664bdd1243dSDimitry Andric   Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;
1665bdd1243dSDimitry Andric 
1666bdd1243dSDimitry Andric   unsigned MaxExtLevel;
1667bdd1243dSDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1668bdd1243dSDimitry Andric 
1669bdd1243dSDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1670bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1671bdd1243dSDimitry Andric   Features["sahf"]   = HasExtLeaf1 && ((ECX >>  0) & 1);
1672bdd1243dSDimitry Andric   Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);
1673bdd1243dSDimitry Andric   Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);
1674bdd1243dSDimitry Andric   Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);
1675bdd1243dSDimitry Andric   Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1676bdd1243dSDimitry Andric   Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);
1677bdd1243dSDimitry Andric   Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1678bdd1243dSDimitry Andric   Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);
1679bdd1243dSDimitry Andric   Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1680bdd1243dSDimitry Andric 
1681bdd1243dSDimitry Andric   Features["64bit"]  = HasExtLeaf1 && ((EDX >> 29) & 1);
1682bdd1243dSDimitry Andric 
1683bdd1243dSDimitry Andric   // Miscellaneous memory related features, detected by
1684bdd1243dSDimitry Andric   // using the 0x80000008 leaf of the CPUID instruction
1685bdd1243dSDimitry Andric   bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
1686bdd1243dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
1687bdd1243dSDimitry Andric   Features["clzero"]   = HasExtLeaf8 && ((EBX >> 0) & 1);
1688bdd1243dSDimitry Andric   Features["rdpru"]    = HasExtLeaf8 && ((EBX >> 4) & 1);
1689bdd1243dSDimitry Andric   Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
1690bdd1243dSDimitry Andric 
1691bdd1243dSDimitry Andric   bool HasLeaf7 =
1692bdd1243dSDimitry Andric       MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1693bdd1243dSDimitry Andric 
1694bdd1243dSDimitry Andric   Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);
1695bdd1243dSDimitry Andric   Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);
1696bdd1243dSDimitry Andric   Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);
1697bdd1243dSDimitry Andric   // AVX2 is only supported if we have the OS save support from AVX.
1698bdd1243dSDimitry Andric   Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;
1699bdd1243dSDimitry Andric   Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);
1700bdd1243dSDimitry Andric   Features["invpcid"]    = HasLeaf7 && ((EBX >> 10) & 1);
1701bdd1243dSDimitry Andric   Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);
1702bdd1243dSDimitry Andric   // AVX512 is only supported if the OS supports the context save for it.
1703bdd1243dSDimitry Andric   Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1704bdd1243dSDimitry Andric   Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1705bdd1243dSDimitry Andric   Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);
1706bdd1243dSDimitry Andric   Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);
1707bdd1243dSDimitry Andric   Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
1708bdd1243dSDimitry Andric   Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1709bdd1243dSDimitry Andric   Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);
1710bdd1243dSDimitry Andric   Features["avx512pf"]   = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
1711bdd1243dSDimitry Andric   Features["avx512er"]   = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
1712bdd1243dSDimitry Andric   Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1713bdd1243dSDimitry Andric   Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);
1714bdd1243dSDimitry Andric   Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1715bdd1243dSDimitry Andric   Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
1716bdd1243dSDimitry Andric 
1717bdd1243dSDimitry Andric   Features["prefetchwt1"]     = HasLeaf7 && ((ECX >>  0) & 1);
1718bdd1243dSDimitry Andric   Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;
1719bdd1243dSDimitry Andric   Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);
1720bdd1243dSDimitry Andric   Features["waitpkg"]         = HasLeaf7 && ((ECX >>  5) & 1);
1721bdd1243dSDimitry Andric   Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;
1722bdd1243dSDimitry Andric   Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);
1723bdd1243dSDimitry Andric   Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);
1724bdd1243dSDimitry Andric   Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;
1725bdd1243dSDimitry Andric   Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1726bdd1243dSDimitry Andric   Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1727bdd1243dSDimitry Andric   Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
1728bdd1243dSDimitry Andric   Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
1729bdd1243dSDimitry Andric   Features["rdpid"]           = HasLeaf7 && ((ECX >> 22) & 1);
1730bdd1243dSDimitry Andric   Features["kl"]              = HasLeaf7 && ((ECX >> 23) & 1); // key locker
1731bdd1243dSDimitry Andric   Features["cldemote"]        = HasLeaf7 && ((ECX >> 25) & 1);
1732bdd1243dSDimitry Andric   Features["movdiri"]         = HasLeaf7 && ((ECX >> 27) & 1);
1733bdd1243dSDimitry Andric   Features["movdir64b"]       = HasLeaf7 && ((ECX >> 28) & 1);
1734bdd1243dSDimitry Andric   Features["enqcmd"]          = HasLeaf7 && ((ECX >> 29) & 1);
1735bdd1243dSDimitry Andric 
1736bdd1243dSDimitry Andric   Features["uintr"]           = HasLeaf7 && ((EDX >> 5) & 1);
1737bdd1243dSDimitry Andric   Features["avx512vp2intersect"] =
1738bdd1243dSDimitry Andric       HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;
1739bdd1243dSDimitry Andric   Features["serialize"]       = HasLeaf7 && ((EDX >> 14) & 1);
1740bdd1243dSDimitry Andric   Features["tsxldtrk"]        = HasLeaf7 && ((EDX >> 16) & 1);
1741bdd1243dSDimitry Andric   // There are two CPUID leafs which information associated with the pconfig
1742bdd1243dSDimitry Andric   // instruction:
1743bdd1243dSDimitry Andric   // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
1744bdd1243dSDimitry Andric   // bit of EDX), while the EAX=0x1b leaf returns information on the
1745bdd1243dSDimitry Andric   // availability of specific pconfig leafs.
1746bdd1243dSDimitry Andric   // The target feature here only refers to the the first of these two.
1747bdd1243dSDimitry Andric   // Users might need to check for the availability of specific pconfig
1748bdd1243dSDimitry Andric   // leaves using cpuid, since that information is ignored while
1749bdd1243dSDimitry Andric   // detecting features using the "-march=native" flag.
1750bdd1243dSDimitry Andric   // For more info, see X86 ISA docs.
1751bdd1243dSDimitry Andric   Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
1752bdd1243dSDimitry Andric   Features["amx-bf16"]   = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;
1753bdd1243dSDimitry Andric   Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;
1754bdd1243dSDimitry Andric   Features["amx-tile"]   = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;
1755bdd1243dSDimitry Andric   Features["amx-int8"]   = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;
1756*8a4dda33SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
1757*8a4dda33SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
1758bdd1243dSDimitry Andric   bool HasLeaf7Subleaf1 =
1759*8a4dda33SDimitry Andric       HasLeaf7 && EAX >= 1 &&
1760*8a4dda33SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
176106c3fb27SDimitry Andric   Features["sha512"]     = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);
176206c3fb27SDimitry Andric   Features["sm3"]        = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);
176306c3fb27SDimitry Andric   Features["sm4"]        = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);
1764bdd1243dSDimitry Andric   Features["raoint"]     = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);
1765bdd1243dSDimitry Andric   Features["avxvnni"]    = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;
1766bdd1243dSDimitry Andric   Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;
1767bdd1243dSDimitry Andric   Features["amx-fp16"]   = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;
1768bdd1243dSDimitry Andric   Features["cmpccxadd"]  = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);
1769bdd1243dSDimitry Andric   Features["hreset"]     = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);
1770bdd1243dSDimitry Andric   Features["avxifma"]    = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;
1771bdd1243dSDimitry Andric   Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;
1772bdd1243dSDimitry Andric   Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;
177306c3fb27SDimitry Andric   Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;
177406c3fb27SDimitry Andric   Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;
1775bdd1243dSDimitry Andric   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
1776bdd1243dSDimitry Andric 
1777bdd1243dSDimitry Andric   bool HasLeafD = MaxLevel >= 0xd &&
1778bdd1243dSDimitry Andric                   !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1779bdd1243dSDimitry Andric 
1780bdd1243dSDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1781bdd1243dSDimitry Andric   Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1782bdd1243dSDimitry Andric   Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1783bdd1243dSDimitry Andric   Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
1784bdd1243dSDimitry Andric 
1785bdd1243dSDimitry Andric   bool HasLeaf14 = MaxLevel >= 0x14 &&
1786bdd1243dSDimitry Andric                   !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
1787bdd1243dSDimitry Andric 
1788bdd1243dSDimitry Andric   Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
1789bdd1243dSDimitry Andric 
1790bdd1243dSDimitry Andric   bool HasLeaf19 =
1791bdd1243dSDimitry Andric       MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);
1792bdd1243dSDimitry Andric   Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);
1793bdd1243dSDimitry Andric 
1794bdd1243dSDimitry Andric   return true;
1795bdd1243dSDimitry Andric }
1796bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1797bdd1243dSDimitry Andric bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1798bdd1243dSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1799bdd1243dSDimitry Andric   if (!P)
1800bdd1243dSDimitry Andric     return false;
1801bdd1243dSDimitry Andric 
1802bdd1243dSDimitry Andric   SmallVector<StringRef, 32> Lines;
1803bdd1243dSDimitry Andric   P->getBuffer().split(Lines, "\n");
1804bdd1243dSDimitry Andric 
1805bdd1243dSDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
1806bdd1243dSDimitry Andric 
1807bdd1243dSDimitry Andric   // Look for the CPU features.
1808bdd1243dSDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
1809bdd1243dSDimitry Andric     if (Lines[I].startswith("Features")) {
1810bdd1243dSDimitry Andric       Lines[I].split(CPUFeatures, ' ');
1811bdd1243dSDimitry Andric       break;
1812bdd1243dSDimitry Andric     }
1813bdd1243dSDimitry Andric 
1814bdd1243dSDimitry Andric #if defined(__aarch64__)
1815bdd1243dSDimitry Andric   // Keep track of which crypto features we have seen
1816bdd1243dSDimitry Andric   enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
1817bdd1243dSDimitry Andric   uint32_t crypto = 0;
1818bdd1243dSDimitry Andric #endif
1819bdd1243dSDimitry Andric 
1820bdd1243dSDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
1821bdd1243dSDimitry Andric     StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
1822bdd1243dSDimitry Andric #if defined(__aarch64__)
1823bdd1243dSDimitry Andric                                    .Case("asimd", "neon")
1824bdd1243dSDimitry Andric                                    .Case("fp", "fp-armv8")
1825bdd1243dSDimitry Andric                                    .Case("crc32", "crc")
1826bdd1243dSDimitry Andric                                    .Case("atomics", "lse")
1827bdd1243dSDimitry Andric                                    .Case("sve", "sve")
1828bdd1243dSDimitry Andric                                    .Case("sve2", "sve2")
1829bdd1243dSDimitry Andric #else
1830bdd1243dSDimitry Andric                                    .Case("half", "fp16")
1831bdd1243dSDimitry Andric                                    .Case("neon", "neon")
1832bdd1243dSDimitry Andric                                    .Case("vfpv3", "vfp3")
1833bdd1243dSDimitry Andric                                    .Case("vfpv3d16", "vfp3d16")
1834bdd1243dSDimitry Andric                                    .Case("vfpv4", "vfp4")
1835bdd1243dSDimitry Andric                                    .Case("idiva", "hwdiv-arm")
1836bdd1243dSDimitry Andric                                    .Case("idivt", "hwdiv")
1837bdd1243dSDimitry Andric #endif
1838bdd1243dSDimitry Andric                                    .Default("");
1839bdd1243dSDimitry Andric 
1840bdd1243dSDimitry Andric #if defined(__aarch64__)
1841bdd1243dSDimitry Andric     // We need to check crypto separately since we need all of the crypto
1842bdd1243dSDimitry Andric     // extensions to enable the subtarget feature
1843bdd1243dSDimitry Andric     if (CPUFeatures[I] == "aes")
1844bdd1243dSDimitry Andric       crypto |= CAP_AES;
1845bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "pmull")
1846bdd1243dSDimitry Andric       crypto |= CAP_PMULL;
1847bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "sha1")
1848bdd1243dSDimitry Andric       crypto |= CAP_SHA1;
1849bdd1243dSDimitry Andric     else if (CPUFeatures[I] == "sha2")
1850bdd1243dSDimitry Andric       crypto |= CAP_SHA2;
1851bdd1243dSDimitry Andric #endif
1852bdd1243dSDimitry Andric 
1853bdd1243dSDimitry Andric     if (LLVMFeatureStr != "")
1854bdd1243dSDimitry Andric       Features[LLVMFeatureStr] = true;
1855bdd1243dSDimitry Andric   }
1856bdd1243dSDimitry Andric 
1857bdd1243dSDimitry Andric #if defined(__aarch64__)
1858bdd1243dSDimitry Andric   // If we have all crypto bits we can add the feature
1859bdd1243dSDimitry Andric   if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
1860bdd1243dSDimitry Andric     Features["crypto"] = true;
1861bdd1243dSDimitry Andric #endif
1862bdd1243dSDimitry Andric 
1863bdd1243dSDimitry Andric   return true;
1864bdd1243dSDimitry Andric }
1865bdd1243dSDimitry Andric #elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
1866bdd1243dSDimitry Andric bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
1867bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
1868bdd1243dSDimitry Andric     Features["neon"] = true;
1869bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
1870bdd1243dSDimitry Andric     Features["crc"] = true;
1871bdd1243dSDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
1872bdd1243dSDimitry Andric     Features["crypto"] = true;
1873bdd1243dSDimitry Andric 
1874bdd1243dSDimitry Andric   return true;
1875bdd1243dSDimitry Andric }
187606c3fb27SDimitry Andric #elif defined(__linux__) && defined(__loongarch__)
187706c3fb27SDimitry Andric #include <sys/auxv.h>
187806c3fb27SDimitry Andric bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
187906c3fb27SDimitry Andric   unsigned long hwcap = getauxval(AT_HWCAP);
188006c3fb27SDimitry Andric   bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU
188106c3fb27SDimitry Andric   uint32_t cpucfg2 = 0x2;
188206c3fb27SDimitry Andric   __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));
188306c3fb27SDimitry Andric 
188406c3fb27SDimitry Andric   Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP
188506c3fb27SDimitry Andric   Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP
188606c3fb27SDimitry Andric 
188706c3fb27SDimitry Andric   Features["lsx"] = hwcap & (1UL << 4);  // HWCAP_LOONGARCH_LSX
188806c3fb27SDimitry Andric   Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX
188906c3fb27SDimitry Andric   Features["lvz"] = hwcap & (1UL << 9);  // HWCAP_LOONGARCH_LVZ
189006c3fb27SDimitry Andric 
189106c3fb27SDimitry Andric   return true;
189206c3fb27SDimitry Andric }
1893bdd1243dSDimitry Andric #else
1894bdd1243dSDimitry Andric bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
1895bdd1243dSDimitry Andric #endif
1896bdd1243dSDimitry Andric 
189706c3fb27SDimitry Andric #if __APPLE__
189806c3fb27SDimitry Andric /// \returns the \p triple, but with the Host's arch spliced in.
189906c3fb27SDimitry Andric static Triple withHostArch(Triple T) {
190006c3fb27SDimitry Andric #if defined(__arm__)
190106c3fb27SDimitry Andric   T.setArch(Triple::arm);
190206c3fb27SDimitry Andric   T.setArchName("arm");
190306c3fb27SDimitry Andric #elif defined(__arm64e__)
190406c3fb27SDimitry Andric   T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);
190506c3fb27SDimitry Andric   T.setArchName("arm64e");
190606c3fb27SDimitry Andric #elif defined(__aarch64__)
190706c3fb27SDimitry Andric   T.setArch(Triple::aarch64);
190806c3fb27SDimitry Andric   T.setArchName("arm64");
190906c3fb27SDimitry Andric #elif defined(__x86_64h__)
191006c3fb27SDimitry Andric   T.setArch(Triple::x86_64);
191106c3fb27SDimitry Andric   T.setArchName("x86_64h");
191206c3fb27SDimitry Andric #elif defined(__x86_64__)
191306c3fb27SDimitry Andric   T.setArch(Triple::x86_64);
191406c3fb27SDimitry Andric   T.setArchName("x86_64");
191506c3fb27SDimitry Andric #elif defined(__powerpc__)
191606c3fb27SDimitry Andric   T.setArch(Triple::ppc);
191706c3fb27SDimitry Andric   T.setArchName("powerpc");
191806c3fb27SDimitry Andric #else
191906c3fb27SDimitry Andric #  error "Unimplemented host arch fixup"
192006c3fb27SDimitry Andric #endif
192106c3fb27SDimitry Andric   return T;
192206c3fb27SDimitry Andric }
192306c3fb27SDimitry Andric #endif
192406c3fb27SDimitry Andric 
1925bdd1243dSDimitry Andric std::string sys::getProcessTriple() {
1926bdd1243dSDimitry Andric   std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
1927bdd1243dSDimitry Andric   Triple PT(Triple::normalize(TargetTripleString));
1928bdd1243dSDimitry Andric 
192906c3fb27SDimitry Andric #if __APPLE__
193006c3fb27SDimitry Andric   /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of
193106c3fb27SDimitry Andric   /// the slices. This fixes that up.
193206c3fb27SDimitry Andric   PT = withHostArch(PT);
193306c3fb27SDimitry Andric #endif
193406c3fb27SDimitry Andric 
1935bdd1243dSDimitry Andric   if (sizeof(void *) == 8 && PT.isArch32Bit())
1936bdd1243dSDimitry Andric     PT = PT.get64BitArchVariant();
1937bdd1243dSDimitry Andric   if (sizeof(void *) == 4 && PT.isArch64Bit())
1938bdd1243dSDimitry Andric     PT = PT.get32BitArchVariant();
1939bdd1243dSDimitry Andric 
1940bdd1243dSDimitry Andric   return PT.str();
1941bdd1243dSDimitry Andric }
1942bdd1243dSDimitry Andric 
1943bdd1243dSDimitry Andric void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {
1944bdd1243dSDimitry Andric #if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
1945bdd1243dSDimitry Andric   std::string CPU = std::string(sys::getHostCPUName());
1946bdd1243dSDimitry Andric   if (CPU == "generic")
1947bdd1243dSDimitry Andric     CPU = "(unknown)";
1948bdd1243dSDimitry Andric   OS << "  Default target: " << sys::getDefaultTargetTriple() << '\n'
1949bdd1243dSDimitry Andric      << "  Host CPU: " << CPU << '\n';
1950bdd1243dSDimitry Andric #endif
1951bdd1243dSDimitry Andric }
1952