xref: /llvm-project/llvm/lib/TargetParser/Host.cpp (revision 19834b4623fd1e7ae5185ed76031b407c3fa7a47)
1f09cf34dSArchibald Elliott //===-- Host.cpp - Implement OS Host Detection ------------------*- C++ -*-===//
2f09cf34dSArchibald Elliott //
3f09cf34dSArchibald Elliott // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f09cf34dSArchibald Elliott // See https://llvm.org/LICENSE.txt for license information.
5f09cf34dSArchibald Elliott // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f09cf34dSArchibald Elliott //
7f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===//
8f09cf34dSArchibald Elliott //
9f09cf34dSArchibald Elliott //  This file implements the operating system Host detection.
10f09cf34dSArchibald Elliott //
11f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===//
12f09cf34dSArchibald Elliott 
13f09cf34dSArchibald Elliott #include "llvm/TargetParser/Host.h"
14f09cf34dSArchibald Elliott #include "llvm/ADT/SmallVector.h"
15f09cf34dSArchibald Elliott #include "llvm/ADT/StringMap.h"
16f09cf34dSArchibald Elliott #include "llvm/ADT/StringRef.h"
17f09cf34dSArchibald Elliott #include "llvm/ADT/StringSwitch.h"
18f09cf34dSArchibald Elliott #include "llvm/Config/llvm-config.h"
19f09cf34dSArchibald Elliott #include "llvm/Support/MemoryBuffer.h"
20f09cf34dSArchibald Elliott #include "llvm/Support/raw_ostream.h"
21f09cf34dSArchibald Elliott #include "llvm/TargetParser/Triple.h"
22f09cf34dSArchibald Elliott #include "llvm/TargetParser/X86TargetParser.h"
23f09cf34dSArchibald Elliott #include <string.h>
24f09cf34dSArchibald Elliott 
25f09cf34dSArchibald Elliott // Include the platform-specific parts of this class.
26f09cf34dSArchibald Elliott #ifdef LLVM_ON_UNIX
27f09cf34dSArchibald Elliott #include "Unix/Host.inc"
28f09cf34dSArchibald Elliott #include <sched.h>
29f09cf34dSArchibald Elliott #endif
30f09cf34dSArchibald Elliott #ifdef _WIN32
31f09cf34dSArchibald Elliott #include "Windows/Host.inc"
32f09cf34dSArchibald Elliott #endif
33f09cf34dSArchibald Elliott #ifdef _MSC_VER
34f09cf34dSArchibald Elliott #include <intrin.h>
35f09cf34dSArchibald Elliott #endif
36f09cf34dSArchibald Elliott #ifdef __MVS__
37f09cf34dSArchibald Elliott #include "llvm/Support/BCD.h"
38f09cf34dSArchibald Elliott #endif
39f09cf34dSArchibald Elliott #if defined(__APPLE__)
40f09cf34dSArchibald Elliott #include <mach/host_info.h>
41f09cf34dSArchibald Elliott #include <mach/mach.h>
42f09cf34dSArchibald Elliott #include <mach/mach_host.h>
43f09cf34dSArchibald Elliott #include <mach/machine.h>
44f09cf34dSArchibald Elliott #include <sys/param.h>
45f09cf34dSArchibald Elliott #include <sys/sysctl.h>
46f09cf34dSArchibald Elliott #endif
47f09cf34dSArchibald Elliott #ifdef _AIX
48f09cf34dSArchibald Elliott #include <sys/systemcfg.h>
49f09cf34dSArchibald Elliott #endif
50f09cf34dSArchibald Elliott #if defined(__sun__) && defined(__svr4__)
51f09cf34dSArchibald Elliott #include <kstat.h>
52f09cf34dSArchibald Elliott #endif
53599f8e11SAiden Grossman #if defined(__GNUC__) || defined(__clang__)
54599f8e11SAiden Grossman #if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
55599f8e11SAiden Grossman #include <cpuid.h>
56599f8e11SAiden Grossman #endif
57599f8e11SAiden Grossman #endif
58f09cf34dSArchibald Elliott 
59f09cf34dSArchibald Elliott #define DEBUG_TYPE "host-detection"
60f09cf34dSArchibald Elliott 
61f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===//
62f09cf34dSArchibald Elliott //
63f09cf34dSArchibald Elliott //  Implementations of the CPU detection routines
64f09cf34dSArchibald Elliott //
65f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===//
66f09cf34dSArchibald Elliott 
67f09cf34dSArchibald Elliott using namespace llvm;
68f09cf34dSArchibald Elliott 
69f09cf34dSArchibald Elliott static std::unique_ptr<llvm::MemoryBuffer>
70f09cf34dSArchibald Elliott     LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
71133f8fa2SElvina Yakubova   const char *CPUInfoFile = "/proc/cpuinfo";
72133f8fa2SElvina Yakubova   if (const char *CpuinfoIntercept = std::getenv("LLVM_CPUINFO"))
73133f8fa2SElvina Yakubova     CPUInfoFile = CpuinfoIntercept;
74f09cf34dSArchibald Elliott   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
75133f8fa2SElvina Yakubova       llvm::MemoryBuffer::getFileAsStream(CPUInfoFile);
76133f8fa2SElvina Yakubova 
77f09cf34dSArchibald Elliott   if (std::error_code EC = Text.getError()) {
78133f8fa2SElvina Yakubova     llvm::errs() << "Can't read " << CPUInfoFile << ": " << EC.message()
79133f8fa2SElvina Yakubova                  << "\n";
80f09cf34dSArchibald Elliott     return nullptr;
81f09cf34dSArchibald Elliott   }
82f09cf34dSArchibald Elliott   return std::move(*Text);
83f09cf34dSArchibald Elliott }
84f09cf34dSArchibald Elliott 
85f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
86f09cf34dSArchibald Elliott   // Access to the Processor Version Register (PVR) on PowerPC is privileged,
87f09cf34dSArchibald Elliott   // and so we must use an operating-system interface to determine the current
88f09cf34dSArchibald Elliott   // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
89f09cf34dSArchibald Elliott   const char *generic = "generic";
90f09cf34dSArchibald Elliott 
91f09cf34dSArchibald Elliott   // The cpu line is second (after the 'processor: 0' line), so if this
92f09cf34dSArchibald Elliott   // buffer is too small then something has changed (or is wrong).
93f09cf34dSArchibald Elliott   StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
94f09cf34dSArchibald Elliott   StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
95f09cf34dSArchibald Elliott 
96f09cf34dSArchibald Elliott   StringRef::const_iterator CIP = CPUInfoStart;
97f09cf34dSArchibald Elliott 
98f09cf34dSArchibald Elliott   StringRef::const_iterator CPUStart = nullptr;
99f09cf34dSArchibald Elliott   size_t CPULen = 0;
100f09cf34dSArchibald Elliott 
101f09cf34dSArchibald Elliott   // We need to find the first line which starts with cpu, spaces, and a colon.
102f09cf34dSArchibald Elliott   // After the colon, there may be some additional spaces and then the cpu type.
103f09cf34dSArchibald Elliott   while (CIP < CPUInfoEnd && CPUStart == nullptr) {
104f09cf34dSArchibald Elliott     if (CIP < CPUInfoEnd && *CIP == '\n')
105f09cf34dSArchibald Elliott       ++CIP;
106f09cf34dSArchibald Elliott 
107f09cf34dSArchibald Elliott     if (CIP < CPUInfoEnd && *CIP == 'c') {
108f09cf34dSArchibald Elliott       ++CIP;
109f09cf34dSArchibald Elliott       if (CIP < CPUInfoEnd && *CIP == 'p') {
110f09cf34dSArchibald Elliott         ++CIP;
111f09cf34dSArchibald Elliott         if (CIP < CPUInfoEnd && *CIP == 'u') {
112f09cf34dSArchibald Elliott           ++CIP;
113f09cf34dSArchibald Elliott           while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
114f09cf34dSArchibald Elliott             ++CIP;
115f09cf34dSArchibald Elliott 
116f09cf34dSArchibald Elliott           if (CIP < CPUInfoEnd && *CIP == ':') {
117f09cf34dSArchibald Elliott             ++CIP;
118f09cf34dSArchibald Elliott             while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
119f09cf34dSArchibald Elliott               ++CIP;
120f09cf34dSArchibald Elliott 
121f09cf34dSArchibald Elliott             if (CIP < CPUInfoEnd) {
122f09cf34dSArchibald Elliott               CPUStart = CIP;
123f09cf34dSArchibald Elliott               while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
124f09cf34dSArchibald Elliott                                           *CIP != ',' && *CIP != '\n'))
125f09cf34dSArchibald Elliott                 ++CIP;
126f09cf34dSArchibald Elliott               CPULen = CIP - CPUStart;
127f09cf34dSArchibald Elliott             }
128f09cf34dSArchibald Elliott           }
129f09cf34dSArchibald Elliott         }
130f09cf34dSArchibald Elliott       }
131f09cf34dSArchibald Elliott     }
132f09cf34dSArchibald Elliott 
133f09cf34dSArchibald Elliott     if (CPUStart == nullptr)
134f09cf34dSArchibald Elliott       while (CIP < CPUInfoEnd && *CIP != '\n')
135f09cf34dSArchibald Elliott         ++CIP;
136f09cf34dSArchibald Elliott   }
137f09cf34dSArchibald Elliott 
138f09cf34dSArchibald Elliott   if (CPUStart == nullptr)
139f09cf34dSArchibald Elliott     return generic;
140f09cf34dSArchibald Elliott 
141f09cf34dSArchibald Elliott   return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
142f09cf34dSArchibald Elliott       .Case("604e", "604e")
143f09cf34dSArchibald Elliott       .Case("604", "604")
144f09cf34dSArchibald Elliott       .Case("7400", "7400")
145f09cf34dSArchibald Elliott       .Case("7410", "7400")
146f09cf34dSArchibald Elliott       .Case("7447", "7400")
147f09cf34dSArchibald Elliott       .Case("7455", "7450")
148f09cf34dSArchibald Elliott       .Case("G4", "g4")
149f09cf34dSArchibald Elliott       .Case("POWER4", "970")
150f09cf34dSArchibald Elliott       .Case("PPC970FX", "970")
151f09cf34dSArchibald Elliott       .Case("PPC970MP", "970")
152f09cf34dSArchibald Elliott       .Case("G5", "g5")
153f09cf34dSArchibald Elliott       .Case("POWER5", "g5")
154f09cf34dSArchibald Elliott       .Case("A2", "a2")
155f09cf34dSArchibald Elliott       .Case("POWER6", "pwr6")
156f09cf34dSArchibald Elliott       .Case("POWER7", "pwr7")
157f09cf34dSArchibald Elliott       .Case("POWER8", "pwr8")
158f09cf34dSArchibald Elliott       .Case("POWER8E", "pwr8")
159f09cf34dSArchibald Elliott       .Case("POWER8NVL", "pwr8")
160f09cf34dSArchibald Elliott       .Case("POWER9", "pwr9")
161f09cf34dSArchibald Elliott       .Case("POWER10", "pwr10")
1621df4d866Sazhan92       .Case("POWER11", "pwr11")
163f09cf34dSArchibald Elliott       // FIXME: If we get a simulator or machine with the capabilities of
164f09cf34dSArchibald Elliott       // mcpu=future, we should revisit this and add the name reported by the
165f09cf34dSArchibald Elliott       // simulator/machine.
166f09cf34dSArchibald Elliott       .Default(generic);
167f09cf34dSArchibald Elliott }
168f09cf34dSArchibald Elliott 
169f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
170f09cf34dSArchibald Elliott   // The cpuid register on arm is not accessible from user space. On Linux,
171f09cf34dSArchibald Elliott   // it is exposed through the /proc/cpuinfo file.
172f09cf34dSArchibald Elliott 
173f09cf34dSArchibald Elliott   // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
174f09cf34dSArchibald Elliott   // in all cases.
175f09cf34dSArchibald Elliott   SmallVector<StringRef, 32> Lines;
176fd38a955SCraig Topper   ProcCpuinfoContent.split(Lines, '\n');
177f09cf34dSArchibald Elliott 
178f09cf34dSArchibald Elliott   // Look for the CPU implementer line.
179f09cf34dSArchibald Elliott   StringRef Implementer;
180f09cf34dSArchibald Elliott   StringRef Hardware;
181f09cf34dSArchibald Elliott   StringRef Part;
182f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
183586ecdf2SKazu Hirata     if (Lines[I].starts_with("CPU implementer"))
184f09cf34dSArchibald Elliott       Implementer = Lines[I].substr(15).ltrim("\t :");
185586ecdf2SKazu Hirata     if (Lines[I].starts_with("Hardware"))
186f09cf34dSArchibald Elliott       Hardware = Lines[I].substr(8).ltrim("\t :");
187586ecdf2SKazu Hirata     if (Lines[I].starts_with("CPU part"))
188f09cf34dSArchibald Elliott       Part = Lines[I].substr(8).ltrim("\t :");
189f09cf34dSArchibald Elliott   }
190f09cf34dSArchibald Elliott 
191f09cf34dSArchibald Elliott   if (Implementer == "0x41") { // ARM Ltd.
192f09cf34dSArchibald Elliott     // MSM8992/8994 may give cpu part for the core that the kernel is running on,
193f09cf34dSArchibald Elliott     // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
194586ecdf2SKazu Hirata     if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996"))
195f09cf34dSArchibald Elliott       return "cortex-a53";
196f09cf34dSArchibald Elliott 
197f09cf34dSArchibald Elliott 
198f09cf34dSArchibald Elliott     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
199f09cf34dSArchibald Elliott     // values correspond to the "Part number" in the CP15/c0 register. The
200f09cf34dSArchibald Elliott     // contents are specified in the various processor manuals.
201f09cf34dSArchibald Elliott     // This corresponds to the Main ID Register in Technical Reference Manuals.
202f09cf34dSArchibald Elliott     // and is used in programs like sys-utils
203f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
204f09cf34dSArchibald Elliott         .Case("0x926", "arm926ej-s")
205f09cf34dSArchibald Elliott         .Case("0xb02", "mpcore")
206f09cf34dSArchibald Elliott         .Case("0xb36", "arm1136j-s")
207f09cf34dSArchibald Elliott         .Case("0xb56", "arm1156t2-s")
208f09cf34dSArchibald Elliott         .Case("0xb76", "arm1176jz-s")
20999be3875SJonathan Thackray         .Case("0xc05", "cortex-a5")
21099be3875SJonathan Thackray         .Case("0xc07", "cortex-a7")
211f09cf34dSArchibald Elliott         .Case("0xc08", "cortex-a8")
212f09cf34dSArchibald Elliott         .Case("0xc09", "cortex-a9")
213f09cf34dSArchibald Elliott         .Case("0xc0f", "cortex-a15")
21499be3875SJonathan Thackray         .Case("0xc0e", "cortex-a17")
215f09cf34dSArchibald Elliott         .Case("0xc20", "cortex-m0")
216f09cf34dSArchibald Elliott         .Case("0xc23", "cortex-m3")
217f09cf34dSArchibald Elliott         .Case("0xc24", "cortex-m4")
21899be3875SJonathan Thackray         .Case("0xc27", "cortex-m7")
21999be3875SJonathan Thackray         .Case("0xd20", "cortex-m23")
22099be3875SJonathan Thackray         .Case("0xd21", "cortex-m33")
2218758e648SJonathan Thackray         .Case("0xd24", "cortex-m52")
222f09cf34dSArchibald Elliott         .Case("0xd22", "cortex-m55")
22399be3875SJonathan Thackray         .Case("0xd23", "cortex-m85")
22499be3875SJonathan Thackray         .Case("0xc18", "cortex-r8")
22599be3875SJonathan Thackray         .Case("0xd13", "cortex-r52")
226917afa88SJonathan Thackray         .Case("0xd16", "cortex-r52plus")
22799be3875SJonathan Thackray         .Case("0xd15", "cortex-r82")
228e50a857fSJonathan Thackray         .Case("0xd14", "cortex-r82ae")
229f09cf34dSArchibald Elliott         .Case("0xd02", "cortex-a34")
230f09cf34dSArchibald Elliott         .Case("0xd04", "cortex-a35")
231f09cf34dSArchibald Elliott         .Case("0xd03", "cortex-a53")
232f09cf34dSArchibald Elliott         .Case("0xd05", "cortex-a55")
233f09cf34dSArchibald Elliott         .Case("0xd46", "cortex-a510")
234066c4524SJonathan Thackray         .Case("0xd80", "cortex-a520")
235e85bfa65SJonathan Thackray         .Case("0xd88", "cortex-a520ae")
236f09cf34dSArchibald Elliott         .Case("0xd07", "cortex-a57")
23799be3875SJonathan Thackray         .Case("0xd06", "cortex-a65")
23899be3875SJonathan Thackray         .Case("0xd43", "cortex-a65ae")
239f09cf34dSArchibald Elliott         .Case("0xd08", "cortex-a72")
240f09cf34dSArchibald Elliott         .Case("0xd09", "cortex-a73")
241f09cf34dSArchibald Elliott         .Case("0xd0a", "cortex-a75")
242f09cf34dSArchibald Elliott         .Case("0xd0b", "cortex-a76")
24399be3875SJonathan Thackray         .Case("0xd0e", "cortex-a76ae")
244f09cf34dSArchibald Elliott         .Case("0xd0d", "cortex-a77")
245f09cf34dSArchibald Elliott         .Case("0xd41", "cortex-a78")
24681601391SJonathan Thackray         .Case("0xd42", "cortex-a78ae")
24799be3875SJonathan Thackray         .Case("0xd4b", "cortex-a78c")
248f09cf34dSArchibald Elliott         .Case("0xd47", "cortex-a710")
249f09cf34dSArchibald Elliott         .Case("0xd4d", "cortex-a715")
250066c4524SJonathan Thackray         .Case("0xd81", "cortex-a720")
251e85bfa65SJonathan Thackray         .Case("0xd89", "cortex-a720ae")
252e80c5955SJonathan Thackray         .Case("0xd87", "cortex-a725")
253f09cf34dSArchibald Elliott         .Case("0xd44", "cortex-x1")
254f09cf34dSArchibald Elliott         .Case("0xd4c", "cortex-x1c")
255f09cf34dSArchibald Elliott         .Case("0xd48", "cortex-x2")
256f09cf34dSArchibald Elliott         .Case("0xd4e", "cortex-x3")
257066c4524SJonathan Thackray         .Case("0xd82", "cortex-x4")
258e80c5955SJonathan Thackray         .Case("0xd85", "cortex-x925")
25999be3875SJonathan Thackray         .Case("0xd4a", "neoverse-e1")
260f09cf34dSArchibald Elliott         .Case("0xd0c", "neoverse-n1")
261f09cf34dSArchibald Elliott         .Case("0xd49", "neoverse-n2")
262a670cdadSJonathan Thackray         .Case("0xd8e", "neoverse-n3")
263f09cf34dSArchibald Elliott         .Case("0xd40", "neoverse-v1")
264f09cf34dSArchibald Elliott         .Case("0xd4f", "neoverse-v2")
265a670cdadSJonathan Thackray         .Case("0xd84", "neoverse-v3")
266a670cdadSJonathan Thackray         .Case("0xd83", "neoverse-v3ae")
267f09cf34dSArchibald Elliott         .Default("generic");
268f09cf34dSArchibald Elliott   }
269f09cf34dSArchibald Elliott 
270f09cf34dSArchibald Elliott   if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
271f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
272f09cf34dSArchibald Elliott       .Case("0x516", "thunderx2t99")
273f09cf34dSArchibald Elliott       .Case("0x0516", "thunderx2t99")
274f09cf34dSArchibald Elliott       .Case("0xaf", "thunderx2t99")
275f09cf34dSArchibald Elliott       .Case("0x0af", "thunderx2t99")
276f09cf34dSArchibald Elliott       .Case("0xa1", "thunderxt88")
277f09cf34dSArchibald Elliott       .Case("0x0a1", "thunderxt88")
278f09cf34dSArchibald Elliott       .Default("generic");
279f09cf34dSArchibald Elliott   }
280f09cf34dSArchibald Elliott 
281f09cf34dSArchibald Elliott   if (Implementer == "0x46") { // Fujitsu Ltd.
282f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
283f09cf34dSArchibald Elliott         .Case("0x001", "a64fx")
284a1197a2cSKinoshita Kotaro         .Case("0x003", "fujitsu-monaka")
285f09cf34dSArchibald Elliott         .Default("generic");
286f09cf34dSArchibald Elliott   }
287f09cf34dSArchibald Elliott 
288f09cf34dSArchibald Elliott   if (Implementer == "0x4e") { // NVIDIA Corporation
289f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
290f09cf34dSArchibald Elliott         .Case("0x004", "carmel")
291f09cf34dSArchibald Elliott         .Default("generic");
292f09cf34dSArchibald Elliott   }
293f09cf34dSArchibald Elliott 
294f09cf34dSArchibald Elliott   if (Implementer == "0x48") // HiSilicon Technologies, Inc.
295f09cf34dSArchibald Elliott     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
296f09cf34dSArchibald Elliott     // values correspond to the "Part number" in the CP15/c0 register. The
297f09cf34dSArchibald Elliott     // contents are specified in the various processor manuals.
298f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
299f09cf34dSArchibald Elliott       .Case("0xd01", "tsv110")
300f09cf34dSArchibald Elliott       .Default("generic");
301f09cf34dSArchibald Elliott 
302f09cf34dSArchibald Elliott   if (Implementer == "0x51") // Qualcomm Technologies, Inc.
303f09cf34dSArchibald Elliott     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
304f09cf34dSArchibald Elliott     // values correspond to the "Part number" in the CP15/c0 register. The
305f09cf34dSArchibald Elliott     // contents are specified in the various processor manuals.
306f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
307f09cf34dSArchibald Elliott         .Case("0x06f", "krait") // APQ8064
308f09cf34dSArchibald Elliott         .Case("0x201", "kryo")
309f09cf34dSArchibald Elliott         .Case("0x205", "kryo")
310f09cf34dSArchibald Elliott         .Case("0x211", "kryo")
311f09cf34dSArchibald Elliott         .Case("0x800", "cortex-a73") // Kryo 2xx Gold
312f09cf34dSArchibald Elliott         .Case("0x801", "cortex-a73") // Kryo 2xx Silver
313f09cf34dSArchibald Elliott         .Case("0x802", "cortex-a75") // Kryo 3xx Gold
314f09cf34dSArchibald Elliott         .Case("0x803", "cortex-a75") // Kryo 3xx Silver
315f09cf34dSArchibald Elliott         .Case("0x804", "cortex-a76") // Kryo 4xx Gold
316f09cf34dSArchibald Elliott         .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver
317f09cf34dSArchibald Elliott         .Case("0xc00", "falkor")
318f09cf34dSArchibald Elliott         .Case("0xc01", "saphira")
3196b9753a0SWei Zhao         .Case("0x001", "oryon-1")
320f09cf34dSArchibald Elliott         .Default("generic");
321f09cf34dSArchibald Elliott   if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
322f09cf34dSArchibald Elliott     // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
323f09cf34dSArchibald Elliott     // any predictive pattern across variants and parts.
324f09cf34dSArchibald Elliott     unsigned Variant = 0, Part = 0;
325f09cf34dSArchibald Elliott 
326f09cf34dSArchibald Elliott     // Look for the CPU variant line, whose value is a 1 digit hexadecimal
327f09cf34dSArchibald Elliott     // number, corresponding to the Variant bits in the CP15/C0 register.
328f09cf34dSArchibald Elliott     for (auto I : Lines)
329f09cf34dSArchibald Elliott       if (I.consume_front("CPU variant"))
330f09cf34dSArchibald Elliott         I.ltrim("\t :").getAsInteger(0, Variant);
331f09cf34dSArchibald Elliott 
332f09cf34dSArchibald Elliott     // Look for the CPU part line, whose value is a 3 digit hexadecimal
333f09cf34dSArchibald Elliott     // number, corresponding to the PartNum bits in the CP15/C0 register.
334f09cf34dSArchibald Elliott     for (auto I : Lines)
335f09cf34dSArchibald Elliott       if (I.consume_front("CPU part"))
336f09cf34dSArchibald Elliott         I.ltrim("\t :").getAsInteger(0, Part);
337f09cf34dSArchibald Elliott 
338f09cf34dSArchibald Elliott     unsigned Exynos = (Variant << 12) | Part;
339f09cf34dSArchibald Elliott     switch (Exynos) {
340f09cf34dSArchibald Elliott     default:
341f09cf34dSArchibald Elliott       // Default by falling through to Exynos M3.
342f09cf34dSArchibald Elliott       [[fallthrough]];
343f09cf34dSArchibald Elliott     case 0x1002:
344f09cf34dSArchibald Elliott       return "exynos-m3";
345f09cf34dSArchibald Elliott     case 0x1003:
346f09cf34dSArchibald Elliott       return "exynos-m4";
347f09cf34dSArchibald Elliott     }
348f09cf34dSArchibald Elliott   }
349f09cf34dSArchibald Elliott 
35038eaea73Spcc   if (Implementer == "0x61") { // Apple
35138eaea73Spcc     return StringSwitch<const char *>(Part)
35238eaea73Spcc         .Case("0x020", "apple-m1")
35338eaea73Spcc         .Case("0x021", "apple-m1")
35438eaea73Spcc         .Case("0x022", "apple-m1")
35538eaea73Spcc         .Case("0x023", "apple-m1")
35638eaea73Spcc         .Case("0x024", "apple-m1")
35738eaea73Spcc         .Case("0x025", "apple-m1")
35838eaea73Spcc         .Case("0x028", "apple-m1")
35938eaea73Spcc         .Case("0x029", "apple-m1")
36038eaea73Spcc         .Case("0x030", "apple-m2")
36138eaea73Spcc         .Case("0x031", "apple-m2")
36238eaea73Spcc         .Case("0x032", "apple-m2")
36338eaea73Spcc         .Case("0x033", "apple-m2")
36438eaea73Spcc         .Case("0x034", "apple-m2")
36538eaea73Spcc         .Case("0x035", "apple-m2")
36638eaea73Spcc         .Case("0x038", "apple-m2")
36738eaea73Spcc         .Case("0x039", "apple-m2")
36838eaea73Spcc         .Case("0x049", "apple-m3")
36938eaea73Spcc         .Case("0x048", "apple-m3")
37038eaea73Spcc         .Default("generic");
37138eaea73Spcc   }
37238eaea73Spcc 
373aa2c0f35SAlbert Huang   if (Implementer == "0x63") { // Arm China.
374aa2c0f35SAlbert Huang     return StringSwitch<const char *>(Part)
375aa2c0f35SAlbert Huang         .Case("0x132", "star-mc1")
376aa2c0f35SAlbert Huang         .Default("generic");
377aa2c0f35SAlbert Huang   }
378aa2c0f35SAlbert Huang 
379a690e867SAlexandros Lamprineas   if (Implementer == "0x6d") { // Microsoft Corporation.
380a690e867SAlexandros Lamprineas     // The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2.
381a690e867SAlexandros Lamprineas     return StringSwitch<const char *>(Part)
382a690e867SAlexandros Lamprineas         .Case("0xd49", "neoverse-n2")
383a690e867SAlexandros Lamprineas         .Default("generic");
384a690e867SAlexandros Lamprineas   }
385a690e867SAlexandros Lamprineas 
386f09cf34dSArchibald Elliott   if (Implementer == "0xc0") { // Ampere Computing
387f09cf34dSArchibald Elliott     return StringSwitch<const char *>(Part)
388f09cf34dSArchibald Elliott         .Case("0xac3", "ampere1")
389fb0af891SPhilipp Tomsich         .Case("0xac4", "ampere1a")
390fbba818aSPhilipp Tomsich         .Case("0xac5", "ampere1b")
391f09cf34dSArchibald Elliott         .Default("generic");
392f09cf34dSArchibald Elliott   }
393f09cf34dSArchibald Elliott 
394f09cf34dSArchibald Elliott   return "generic";
395f09cf34dSArchibald Elliott }
396f09cf34dSArchibald Elliott 
397f09cf34dSArchibald Elliott namespace {
398f09cf34dSArchibald Elliott StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {
399f09cf34dSArchibald Elliott   switch (Id) {
400f09cf34dSArchibald Elliott     case 2064:  // z900 not supported by LLVM
401f09cf34dSArchibald Elliott     case 2066:
402f09cf34dSArchibald Elliott     case 2084:  // z990 not supported by LLVM
403f09cf34dSArchibald Elliott     case 2086:
404f09cf34dSArchibald Elliott     case 2094:  // z9-109 not supported by LLVM
405f09cf34dSArchibald Elliott     case 2096:
406f09cf34dSArchibald Elliott       return "generic";
407f09cf34dSArchibald Elliott     case 2097:
408f09cf34dSArchibald Elliott     case 2098:
409f09cf34dSArchibald Elliott       return "z10";
410f09cf34dSArchibald Elliott     case 2817:
411f09cf34dSArchibald Elliott     case 2818:
412f09cf34dSArchibald Elliott       return "z196";
413f09cf34dSArchibald Elliott     case 2827:
414f09cf34dSArchibald Elliott     case 2828:
415f09cf34dSArchibald Elliott       return "zEC12";
416f09cf34dSArchibald Elliott     case 2964:
417f09cf34dSArchibald Elliott     case 2965:
418f09cf34dSArchibald Elliott       return HaveVectorSupport? "z13" : "zEC12";
419f09cf34dSArchibald Elliott     case 3906:
420f09cf34dSArchibald Elliott     case 3907:
421f09cf34dSArchibald Elliott       return HaveVectorSupport? "z14" : "zEC12";
422f09cf34dSArchibald Elliott     case 8561:
423f09cf34dSArchibald Elliott     case 8562:
424f09cf34dSArchibald Elliott       return HaveVectorSupport? "z15" : "zEC12";
425f09cf34dSArchibald Elliott     case 3931:
426f09cf34dSArchibald Elliott     case 3932:
427f09cf34dSArchibald Elliott       return HaveVectorSupport? "z16" : "zEC12";
4288424bf20SUlrich Weigand     case 9175:
4298424bf20SUlrich Weigand     case 9176:
4308424bf20SUlrich Weigand     default:
4318424bf20SUlrich Weigand       return HaveVectorSupport? "arch15" : "zEC12";
432f09cf34dSArchibald Elliott   }
433f09cf34dSArchibald Elliott }
434f09cf34dSArchibald Elliott } // end anonymous namespace
435f09cf34dSArchibald Elliott 
436f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
437f09cf34dSArchibald Elliott   // STIDP is a privileged operation, so use /proc/cpuinfo instead.
438f09cf34dSArchibald Elliott 
439f09cf34dSArchibald Elliott   // The "processor 0:" line comes after a fair amount of other information,
440f09cf34dSArchibald Elliott   // including a cache breakdown, but this should be plenty.
441f09cf34dSArchibald Elliott   SmallVector<StringRef, 32> Lines;
442fd38a955SCraig Topper   ProcCpuinfoContent.split(Lines, '\n');
443f09cf34dSArchibald Elliott 
444f09cf34dSArchibald Elliott   // Look for the CPU features.
445f09cf34dSArchibald Elliott   SmallVector<StringRef, 32> CPUFeatures;
446f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
447586ecdf2SKazu Hirata     if (Lines[I].starts_with("features")) {
448f09cf34dSArchibald Elliott       size_t Pos = Lines[I].find(':');
449f09cf34dSArchibald Elliott       if (Pos != StringRef::npos) {
450f09cf34dSArchibald Elliott         Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
451f09cf34dSArchibald Elliott         break;
452f09cf34dSArchibald Elliott       }
453f09cf34dSArchibald Elliott     }
454f09cf34dSArchibald Elliott 
455f09cf34dSArchibald Elliott   // We need to check for the presence of vector support independently of
456f09cf34dSArchibald Elliott   // the machine type, since we may only use the vector register set when
457f09cf34dSArchibald Elliott   // supported by the kernel (and hypervisor).
458f09cf34dSArchibald Elliott   bool HaveVectorSupport = false;
459f09cf34dSArchibald Elliott   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
460f09cf34dSArchibald Elliott     if (CPUFeatures[I] == "vx")
461f09cf34dSArchibald Elliott       HaveVectorSupport = true;
462f09cf34dSArchibald Elliott   }
463f09cf34dSArchibald Elliott 
464f09cf34dSArchibald Elliott   // Now check the processor machine type.
465f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
466586ecdf2SKazu Hirata     if (Lines[I].starts_with("processor ")) {
467f09cf34dSArchibald Elliott       size_t Pos = Lines[I].find("machine = ");
468f09cf34dSArchibald Elliott       if (Pos != StringRef::npos) {
469f09cf34dSArchibald Elliott         Pos += sizeof("machine = ") - 1;
470f09cf34dSArchibald Elliott         unsigned int Id;
471f09cf34dSArchibald Elliott         if (!Lines[I].drop_front(Pos).getAsInteger(10, Id))
472f09cf34dSArchibald Elliott           return getCPUNameFromS390Model(Id, HaveVectorSupport);
473f09cf34dSArchibald Elliott       }
474f09cf34dSArchibald Elliott       break;
475f09cf34dSArchibald Elliott     }
476f09cf34dSArchibald Elliott   }
477f09cf34dSArchibald Elliott 
478f09cf34dSArchibald Elliott   return "generic";
479f09cf34dSArchibald Elliott }
480f09cf34dSArchibald Elliott 
481f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {
482f09cf34dSArchibald Elliott   // There are 24 lines in /proc/cpuinfo
483f09cf34dSArchibald Elliott   SmallVector<StringRef> Lines;
484fd38a955SCraig Topper   ProcCpuinfoContent.split(Lines, '\n');
485f09cf34dSArchibald Elliott 
486f09cf34dSArchibald Elliott   // Look for uarch line to determine cpu name
487f09cf34dSArchibald Elliott   StringRef UArch;
488f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
489586ecdf2SKazu Hirata     if (Lines[I].starts_with("uarch")) {
490f09cf34dSArchibald Elliott       UArch = Lines[I].substr(5).ltrim("\t :");
491f09cf34dSArchibald Elliott       break;
492f09cf34dSArchibald Elliott     }
493f09cf34dSArchibald Elliott   }
494f09cf34dSArchibald Elliott 
495f09cf34dSArchibald Elliott   return StringSwitch<const char *>(UArch)
496f09cf34dSArchibald Elliott       .Case("sifive,u74-mc", "sifive-u74")
497f09cf34dSArchibald Elliott       .Case("sifive,bullet0", "sifive-u74")
498578cf724SYingwei Zheng       .Default("");
499f09cf34dSArchibald Elliott }
500f09cf34dSArchibald Elliott 
501f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForBPF() {
502f09cf34dSArchibald Elliott #if !defined(__linux__) || !defined(__x86_64__)
503f09cf34dSArchibald Elliott   return "generic";
504f09cf34dSArchibald Elliott #else
505f09cf34dSArchibald Elliott   uint8_t v3_insns[40] __attribute__ ((aligned (8))) =
506f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
507f09cf34dSArchibald Elliott     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
508f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
509f09cf34dSArchibald Elliott       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
510f09cf34dSArchibald Elliott       /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
511f09cf34dSArchibald Elliott       0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
512f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
513f09cf34dSArchibald Elliott       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
514f09cf34dSArchibald Elliott       /* BPF_EXIT_INSN() */
515f09cf34dSArchibald Elliott       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
516f09cf34dSArchibald Elliott 
517f09cf34dSArchibald Elliott   uint8_t v2_insns[40] __attribute__ ((aligned (8))) =
518f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
519f09cf34dSArchibald Elliott     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
520f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
521f09cf34dSArchibald Elliott       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
522f09cf34dSArchibald Elliott       /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
523f09cf34dSArchibald Elliott       0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
524f09cf34dSArchibald Elliott       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
525f09cf34dSArchibald Elliott       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
526f09cf34dSArchibald Elliott       /* BPF_EXIT_INSN() */
527f09cf34dSArchibald Elliott       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
528f09cf34dSArchibald Elliott 
529f09cf34dSArchibald Elliott   struct bpf_prog_load_attr {
530f09cf34dSArchibald Elliott     uint32_t prog_type;
531f09cf34dSArchibald Elliott     uint32_t insn_cnt;
532f09cf34dSArchibald Elliott     uint64_t insns;
533f09cf34dSArchibald Elliott     uint64_t license;
534f09cf34dSArchibald Elliott     uint32_t log_level;
535f09cf34dSArchibald Elliott     uint32_t log_size;
536f09cf34dSArchibald Elliott     uint64_t log_buf;
537f09cf34dSArchibald Elliott     uint32_t kern_version;
538f09cf34dSArchibald Elliott     uint32_t prog_flags;
539f09cf34dSArchibald Elliott   } attr = {};
540f09cf34dSArchibald Elliott   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
541f09cf34dSArchibald Elliott   attr.insn_cnt = 5;
542f09cf34dSArchibald Elliott   attr.insns = (uint64_t)v3_insns;
543f09cf34dSArchibald Elliott   attr.license = (uint64_t)"DUMMY";
544f09cf34dSArchibald Elliott 
545f09cf34dSArchibald Elliott   int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,
546f09cf34dSArchibald Elliott                    sizeof(attr));
547f09cf34dSArchibald Elliott   if (fd >= 0) {
548f09cf34dSArchibald Elliott     close(fd);
549f09cf34dSArchibald Elliott     return "v3";
550f09cf34dSArchibald Elliott   }
551f09cf34dSArchibald Elliott 
552f09cf34dSArchibald Elliott   /* Clear the whole attr in case its content changed by syscall. */
553f09cf34dSArchibald Elliott   memset(&attr, 0, sizeof(attr));
554f09cf34dSArchibald Elliott   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
555f09cf34dSArchibald Elliott   attr.insn_cnt = 5;
556f09cf34dSArchibald Elliott   attr.insns = (uint64_t)v2_insns;
557f09cf34dSArchibald Elliott   attr.license = (uint64_t)"DUMMY";
558f09cf34dSArchibald Elliott   fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
559f09cf34dSArchibald Elliott   if (fd >= 0) {
560f09cf34dSArchibald Elliott     close(fd);
561f09cf34dSArchibald Elliott     return "v2";
562f09cf34dSArchibald Elliott   }
563f09cf34dSArchibald Elliott   return "v1";
564f09cf34dSArchibald Elliott #endif
565f09cf34dSArchibald Elliott }
566f09cf34dSArchibald Elliott 
567599f8e11SAiden Grossman #if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) ||            \
568599f8e11SAiden Grossman     defined(_M_X64)
569f09cf34dSArchibald Elliott 
570f09cf34dSArchibald Elliott /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
571f09cf34dSArchibald Elliott /// the specified arguments.  If we can't run cpuid on the host, return true.
572f09cf34dSArchibald Elliott static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
573f09cf34dSArchibald Elliott                                unsigned *rECX, unsigned *rEDX) {
574599f8e11SAiden Grossman #if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
575599f8e11SAiden Grossman   return !__get_cpuid(value, rEAX, rEBX, rECX, rEDX);
576f09cf34dSArchibald Elliott #elif defined(_MSC_VER)
577f09cf34dSArchibald Elliott   // The MSVC intrinsic is portable across x86 and x64.
578f09cf34dSArchibald Elliott   int registers[4];
579f09cf34dSArchibald Elliott   __cpuid(registers, value);
580f09cf34dSArchibald Elliott   *rEAX = registers[0];
581f09cf34dSArchibald Elliott   *rEBX = registers[1];
582f09cf34dSArchibald Elliott   *rECX = registers[2];
583f09cf34dSArchibald Elliott   *rEDX = registers[3];
584f09cf34dSArchibald Elliott   return false;
585f09cf34dSArchibald Elliott #else
586f09cf34dSArchibald Elliott   return true;
587f09cf34dSArchibald Elliott #endif
588f09cf34dSArchibald Elliott }
589f09cf34dSArchibald Elliott 
590f09cf34dSArchibald Elliott namespace llvm {
591f09cf34dSArchibald Elliott namespace sys {
592f09cf34dSArchibald Elliott namespace detail {
593f09cf34dSArchibald Elliott namespace x86 {
594f09cf34dSArchibald Elliott 
595f09cf34dSArchibald Elliott VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
596f09cf34dSArchibald Elliott   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
597f09cf34dSArchibald Elliott   if (MaxLeaf == nullptr)
598f09cf34dSArchibald Elliott     MaxLeaf = &EAX;
599f09cf34dSArchibald Elliott   else
600f09cf34dSArchibald Elliott     *MaxLeaf = 0;
601f09cf34dSArchibald Elliott 
602f09cf34dSArchibald Elliott   if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)
603f09cf34dSArchibald Elliott     return VendorSignatures::UNKNOWN;
604f09cf34dSArchibald Elliott 
605f09cf34dSArchibald Elliott   // "Genu ineI ntel"
606f09cf34dSArchibald Elliott   if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)
607f09cf34dSArchibald Elliott     return VendorSignatures::GENUINE_INTEL;
608f09cf34dSArchibald Elliott 
609f09cf34dSArchibald Elliott   // "Auth enti cAMD"
610f09cf34dSArchibald Elliott   if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)
611f09cf34dSArchibald Elliott     return VendorSignatures::AUTHENTIC_AMD;
612f09cf34dSArchibald Elliott 
613f09cf34dSArchibald Elliott   return VendorSignatures::UNKNOWN;
614f09cf34dSArchibald Elliott }
615f09cf34dSArchibald Elliott 
616f09cf34dSArchibald Elliott } // namespace x86
617f09cf34dSArchibald Elliott } // namespace detail
618f09cf34dSArchibald Elliott } // namespace sys
619f09cf34dSArchibald Elliott } // namespace llvm
620f09cf34dSArchibald Elliott 
621f09cf34dSArchibald Elliott using namespace llvm::sys::detail::x86;
622f09cf34dSArchibald Elliott 
623f09cf34dSArchibald Elliott /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
624f09cf34dSArchibald Elliott /// the 4 values in the specified arguments.  If we can't run cpuid on the host,
625f09cf34dSArchibald Elliott /// return true.
626f09cf34dSArchibald Elliott static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
627f09cf34dSArchibald Elliott                                  unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
628f09cf34dSArchibald Elliott                                  unsigned *rEDX) {
629599f8e11SAiden Grossman   // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
630599f8e11SAiden Grossman   // are such that __cpuidex is defined within cpuid.h for both, we can remove
631599f8e11SAiden Grossman   // the __get_cpuid_count function and share the MSVC implementation between
632599f8e11SAiden Grossman   // all three.
633599f8e11SAiden Grossman #if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
634599f8e11SAiden Grossman   return !__get_cpuid_count(value, subleaf, rEAX, rEBX, rECX, rEDX);
635f09cf34dSArchibald Elliott #elif defined(_MSC_VER)
636f09cf34dSArchibald Elliott   int registers[4];
637f09cf34dSArchibald Elliott   __cpuidex(registers, value, subleaf);
638f09cf34dSArchibald Elliott   *rEAX = registers[0];
639f09cf34dSArchibald Elliott   *rEBX = registers[1];
640f09cf34dSArchibald Elliott   *rECX = registers[2];
641f09cf34dSArchibald Elliott   *rEDX = registers[3];
642f09cf34dSArchibald Elliott   return false;
643f09cf34dSArchibald Elliott #else
644f09cf34dSArchibald Elliott   return true;
645f09cf34dSArchibald Elliott #endif
646f09cf34dSArchibald Elliott }
647f09cf34dSArchibald Elliott 
648f09cf34dSArchibald Elliott // Read control register 0 (XCR0). Used to detect features such as AVX.
649f09cf34dSArchibald Elliott static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
650599f8e11SAiden Grossman   // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
651599f8e11SAiden Grossman   // are such that _xgetbv is supported by both, we can unify the implementation
652599f8e11SAiden Grossman   // with MSVC and remove all inline assembly.
653f09cf34dSArchibald Elliott #if defined(__GNUC__) || defined(__clang__)
654f09cf34dSArchibald Elliott   // Check xgetbv; this uses a .byte sequence instead of the instruction
655f09cf34dSArchibald Elliott   // directly because older assemblers do not include support for xgetbv and
656f09cf34dSArchibald Elliott   // there is no easy way to conditionally compile based on the assembler used.
657f09cf34dSArchibald Elliott   __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
658f09cf34dSArchibald Elliott   return false;
659f09cf34dSArchibald Elliott #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
660f09cf34dSArchibald Elliott   unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
661f09cf34dSArchibald Elliott   *rEAX = Result;
662f09cf34dSArchibald Elliott   *rEDX = Result >> 32;
663f09cf34dSArchibald Elliott   return false;
664f09cf34dSArchibald Elliott #else
665f09cf34dSArchibald Elliott   return true;
666f09cf34dSArchibald Elliott #endif
667f09cf34dSArchibald Elliott }
668f09cf34dSArchibald Elliott 
669f09cf34dSArchibald Elliott static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
670f09cf34dSArchibald Elliott                                  unsigned *Model) {
671f09cf34dSArchibald Elliott   *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
672f09cf34dSArchibald Elliott   *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
673f09cf34dSArchibald Elliott   if (*Family == 6 || *Family == 0xf) {
674f09cf34dSArchibald Elliott     if (*Family == 0xf)
675f09cf34dSArchibald Elliott       // Examine extended family ID if family ID is F.
676f09cf34dSArchibald Elliott       *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
677f09cf34dSArchibald Elliott     // Examine extended model ID if family ID is 6 or F.
678f09cf34dSArchibald Elliott     *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
679f09cf34dSArchibald Elliott   }
680f09cf34dSArchibald Elliott }
681f09cf34dSArchibald Elliott 
68287e914dbSAiden Grossman #define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
683f09cf34dSArchibald Elliott 
68487e914dbSAiden Grossman static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,
68587e914dbSAiden Grossman                                                  unsigned Model,
68687e914dbSAiden Grossman                                                  const unsigned *Features,
68787e914dbSAiden Grossman                                                  unsigned *Type,
68887e914dbSAiden Grossman                                                  unsigned *Subtype) {
689f09cf34dSArchibald Elliott   StringRef CPU;
690f09cf34dSArchibald Elliott 
691f09cf34dSArchibald Elliott   switch (Family) {
692f09cf34dSArchibald Elliott   case 3:
693f09cf34dSArchibald Elliott     CPU = "i386";
694f09cf34dSArchibald Elliott     break;
695f09cf34dSArchibald Elliott   case 4:
696f09cf34dSArchibald Elliott     CPU = "i486";
697f09cf34dSArchibald Elliott     break;
698f09cf34dSArchibald Elliott   case 5:
699f09cf34dSArchibald Elliott     if (testFeature(X86::FEATURE_MMX)) {
700f09cf34dSArchibald Elliott       CPU = "pentium-mmx";
701f09cf34dSArchibald Elliott       break;
702f09cf34dSArchibald Elliott     }
703f09cf34dSArchibald Elliott     CPU = "pentium";
704f09cf34dSArchibald Elliott     break;
705f09cf34dSArchibald Elliott   case 6:
706f09cf34dSArchibald Elliott     switch (Model) {
707f09cf34dSArchibald Elliott     case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
708f09cf34dSArchibald Elliott                // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
709f09cf34dSArchibald Elliott                // mobile processor, Intel Core 2 Extreme processor, Intel
710f09cf34dSArchibald Elliott                // Pentium Dual-Core processor, Intel Xeon processor, model
711f09cf34dSArchibald Elliott                // 0Fh. All processors are manufactured using the 65 nm process.
712f09cf34dSArchibald Elliott     case 0x16: // Intel Celeron processor model 16h. All processors are
713f09cf34dSArchibald Elliott                // manufactured using the 65 nm process
714f09cf34dSArchibald Elliott       CPU = "core2";
715f09cf34dSArchibald Elliott       *Type = X86::INTEL_CORE2;
716f09cf34dSArchibald Elliott       break;
717f09cf34dSArchibald Elliott     case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
718f09cf34dSArchibald Elliott                // 17h. All processors are manufactured using the 45 nm process.
719f09cf34dSArchibald Elliott                //
720f09cf34dSArchibald Elliott                // 45nm: Penryn , Wolfdale, Yorkfield (XE)
721f09cf34dSArchibald Elliott     case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
722f09cf34dSArchibald Elliott                // the 45 nm process.
723f09cf34dSArchibald Elliott       CPU = "penryn";
724f09cf34dSArchibald Elliott       *Type = X86::INTEL_CORE2;
725f09cf34dSArchibald Elliott       break;
726f09cf34dSArchibald Elliott     case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
727f09cf34dSArchibald Elliott                // processors are manufactured using the 45 nm process.
728f09cf34dSArchibald Elliott     case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
729f09cf34dSArchibald Elliott                // As found in a Summer 2010 model iMac.
730f09cf34dSArchibald Elliott     case 0x1f:
731f09cf34dSArchibald Elliott     case 0x2e:              // Nehalem EX
732f09cf34dSArchibald Elliott       CPU = "nehalem";
733f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
734f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_NEHALEM;
735f09cf34dSArchibald Elliott       break;
736f09cf34dSArchibald Elliott     case 0x25: // Intel Core i7, laptop version.
737f09cf34dSArchibald Elliott     case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
738f09cf34dSArchibald Elliott                // processors are manufactured using the 32 nm process.
739f09cf34dSArchibald Elliott     case 0x2f: // Westmere EX
740f09cf34dSArchibald Elliott       CPU = "westmere";
741f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
742f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_WESTMERE;
743f09cf34dSArchibald Elliott       break;
744f09cf34dSArchibald Elliott     case 0x2a: // Intel Core i7 processor. All processors are manufactured
745f09cf34dSArchibald Elliott                // using the 32 nm process.
746f09cf34dSArchibald Elliott     case 0x2d:
747f09cf34dSArchibald Elliott       CPU = "sandybridge";
748f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
749f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
750f09cf34dSArchibald Elliott       break;
751f09cf34dSArchibald Elliott     case 0x3a:
752f09cf34dSArchibald Elliott     case 0x3e:              // Ivy Bridge EP
753f09cf34dSArchibald Elliott       CPU = "ivybridge";
754f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
755f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
756f09cf34dSArchibald Elliott       break;
757f09cf34dSArchibald Elliott 
758f09cf34dSArchibald Elliott     // Haswell:
759f09cf34dSArchibald Elliott     case 0x3c:
760f09cf34dSArchibald Elliott     case 0x3f:
761f09cf34dSArchibald Elliott     case 0x45:
762f09cf34dSArchibald Elliott     case 0x46:
763f09cf34dSArchibald Elliott       CPU = "haswell";
764f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
765f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_HASWELL;
766f09cf34dSArchibald Elliott       break;
767f09cf34dSArchibald Elliott 
768f09cf34dSArchibald Elliott     // Broadwell:
769f09cf34dSArchibald Elliott     case 0x3d:
770f09cf34dSArchibald Elliott     case 0x47:
771f09cf34dSArchibald Elliott     case 0x4f:
772f09cf34dSArchibald Elliott     case 0x56:
773f09cf34dSArchibald Elliott       CPU = "broadwell";
774f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
775f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_BROADWELL;
776f09cf34dSArchibald Elliott       break;
777f09cf34dSArchibald Elliott 
778f09cf34dSArchibald Elliott     // Skylake:
779f09cf34dSArchibald Elliott     case 0x4e:              // Skylake mobile
780f09cf34dSArchibald Elliott     case 0x5e:              // Skylake desktop
781f09cf34dSArchibald Elliott     case 0x8e:              // Kaby Lake mobile
782f09cf34dSArchibald Elliott     case 0x9e:              // Kaby Lake desktop
783f09cf34dSArchibald Elliott     case 0xa5:              // Comet Lake-H/S
784f09cf34dSArchibald Elliott     case 0xa6:              // Comet Lake-U
785f09cf34dSArchibald Elliott       CPU = "skylake";
786f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
787f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_SKYLAKE;
788f09cf34dSArchibald Elliott       break;
789f09cf34dSArchibald Elliott 
790f09cf34dSArchibald Elliott     // Rocketlake:
791f09cf34dSArchibald Elliott     case 0xa7:
792f09cf34dSArchibald Elliott       CPU = "rocketlake";
793f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
794f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_ROCKETLAKE;
795f09cf34dSArchibald Elliott       break;
796f09cf34dSArchibald Elliott 
797f09cf34dSArchibald Elliott     // Skylake Xeon:
798f09cf34dSArchibald Elliott     case 0x55:
799f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
800f09cf34dSArchibald Elliott       if (testFeature(X86::FEATURE_AVX512BF16)) {
801f09cf34dSArchibald Elliott         CPU = "cooperlake";
802f09cf34dSArchibald Elliott         *Subtype = X86::INTEL_COREI7_COOPERLAKE;
803f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
804f09cf34dSArchibald Elliott         CPU = "cascadelake";
805f09cf34dSArchibald Elliott         *Subtype = X86::INTEL_COREI7_CASCADELAKE;
806f09cf34dSArchibald Elliott       } else {
807f09cf34dSArchibald Elliott         CPU = "skylake-avx512";
808f09cf34dSArchibald Elliott         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
809f09cf34dSArchibald Elliott       }
810f09cf34dSArchibald Elliott       break;
811f09cf34dSArchibald Elliott 
812f09cf34dSArchibald Elliott     // Cannonlake:
813f09cf34dSArchibald Elliott     case 0x66:
814f09cf34dSArchibald Elliott       CPU = "cannonlake";
815f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
816f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_CANNONLAKE;
817f09cf34dSArchibald Elliott       break;
818f09cf34dSArchibald Elliott 
819f09cf34dSArchibald Elliott     // Icelake:
820f09cf34dSArchibald Elliott     case 0x7d:
821f09cf34dSArchibald Elliott     case 0x7e:
822f09cf34dSArchibald Elliott       CPU = "icelake-client";
823f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
824f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
825f09cf34dSArchibald Elliott       break;
826f09cf34dSArchibald Elliott 
827f09cf34dSArchibald Elliott     // Tigerlake:
828f09cf34dSArchibald Elliott     case 0x8c:
829f09cf34dSArchibald Elliott     case 0x8d:
830f09cf34dSArchibald Elliott       CPU = "tigerlake";
831f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
832f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_TIGERLAKE;
833f09cf34dSArchibald Elliott       break;
834f09cf34dSArchibald Elliott 
835f09cf34dSArchibald Elliott     // Alderlake:
836f09cf34dSArchibald Elliott     case 0x97:
837f09cf34dSArchibald Elliott     case 0x9a:
8383348b468SPhoebe Wang       CPU = "alderlake";
8393348b468SPhoebe Wang       *Type = X86::INTEL_COREI7;
8403348b468SPhoebe Wang       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
8413348b468SPhoebe Wang       break;
8423348b468SPhoebe Wang 
8436acff539SFreddy Ye     // Gracemont
8446acff539SFreddy Ye     case 0xbe:
845a6393129SPhoebe Wang       CPU = "gracemont";
8463348b468SPhoebe Wang       *Type = X86::INTEL_COREI7;
8473348b468SPhoebe Wang       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
8483348b468SPhoebe Wang       break;
8493348b468SPhoebe Wang 
850f09cf34dSArchibald Elliott     // Raptorlake:
851f09cf34dSArchibald Elliott     case 0xb7:
852cafbcfa0SFreddy Ye     case 0xba:
853cafbcfa0SFreddy Ye     case 0xbf:
8543348b468SPhoebe Wang       CPU = "raptorlake";
8553348b468SPhoebe Wang       *Type = X86::INTEL_COREI7;
8563348b468SPhoebe Wang       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
8573348b468SPhoebe Wang       break;
8583348b468SPhoebe Wang 
859f09cf34dSArchibald Elliott     // Meteorlake:
860f09cf34dSArchibald Elliott     case 0xaa:
861f09cf34dSArchibald Elliott     case 0xac:
8623348b468SPhoebe Wang       CPU = "meteorlake";
863f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
864f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
865f09cf34dSArchibald Elliott       break;
866f09cf34dSArchibald Elliott 
867c9d92e66SFreddy Ye     // Arrowlake:
868c9d92e66SFreddy Ye     case 0xc5:
8699e3d4653SFreddy Ye     // Arrowlake U:
8709e3d4653SFreddy Ye     case 0xb5:
871c9d92e66SFreddy Ye       CPU = "arrowlake";
872c9d92e66SFreddy Ye       *Type = X86::INTEL_COREI7;
873c9d92e66SFreddy Ye       *Subtype = X86::INTEL_COREI7_ARROWLAKE;
874c9d92e66SFreddy Ye       break;
875c9d92e66SFreddy Ye 
876c9d92e66SFreddy Ye     // Arrowlake S:
877c9d92e66SFreddy Ye     case 0xc6:
8783348b468SPhoebe Wang       CPU = "arrowlake-s";
8793348b468SPhoebe Wang       *Type = X86::INTEL_COREI7;
8803348b468SPhoebe Wang       *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;
8813348b468SPhoebe Wang       break;
8823348b468SPhoebe Wang 
883c9d92e66SFreddy Ye     // Lunarlake:
884c9d92e66SFreddy Ye     case 0xbd:
8853348b468SPhoebe Wang       CPU = "lunarlake";
886c9d92e66SFreddy Ye       *Type = X86::INTEL_COREI7;
887c9d92e66SFreddy Ye       *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;
888c9d92e66SFreddy Ye       break;
889c9d92e66SFreddy Ye 
890278e533eSFreddy Ye     // Pantherlake:
891278e533eSFreddy Ye     case 0xcc:
892278e533eSFreddy Ye       CPU = "pantherlake";
893278e533eSFreddy Ye       *Type = X86::INTEL_COREI7;
894278e533eSFreddy Ye       *Subtype = X86::INTEL_COREI7_PANTHERLAKE;
895278e533eSFreddy Ye       break;
896278e533eSFreddy Ye 
897f09cf34dSArchibald Elliott     // Graniterapids:
898f09cf34dSArchibald Elliott     case 0xad:
899f09cf34dSArchibald Elliott       CPU = "graniterapids";
900f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
901f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS;
902f09cf34dSArchibald Elliott       break;
903f09cf34dSArchibald Elliott 
9046d23a3faSFreddy Ye     // Granite Rapids D:
9056d23a3faSFreddy Ye     case 0xae:
9066d23a3faSFreddy Ye       CPU = "graniterapids-d";
9076d23a3faSFreddy Ye       *Type = X86::INTEL_COREI7;
9086d23a3faSFreddy Ye       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;
9096d23a3faSFreddy Ye       break;
9106d23a3faSFreddy Ye 
911f09cf34dSArchibald Elliott     // Icelake Xeon:
912f09cf34dSArchibald Elliott     case 0x6a:
913f09cf34dSArchibald Elliott     case 0x6c:
914f09cf34dSArchibald Elliott       CPU = "icelake-server";
915f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
916f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;
917f09cf34dSArchibald Elliott       break;
918f09cf34dSArchibald Elliott 
91927b8f54fSFreddy Ye     // Emerald Rapids:
92027b8f54fSFreddy Ye     case 0xcf:
9213348b468SPhoebe Wang       CPU = "emeraldrapids";
9223348b468SPhoebe Wang       *Type = X86::INTEL_COREI7;
9233348b468SPhoebe Wang       *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;
9243348b468SPhoebe Wang       break;
9253348b468SPhoebe Wang 
926f09cf34dSArchibald Elliott     // Sapphire Rapids:
927f09cf34dSArchibald Elliott     case 0x8f:
928f09cf34dSArchibald Elliott       CPU = "sapphirerapids";
929f09cf34dSArchibald Elliott       *Type = X86::INTEL_COREI7;
930f09cf34dSArchibald Elliott       *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;
931f09cf34dSArchibald Elliott       break;
932f09cf34dSArchibald Elliott 
933f09cf34dSArchibald Elliott     case 0x1c: // Most 45 nm Intel Atom processors
934f09cf34dSArchibald Elliott     case 0x26: // 45 nm Atom Lincroft
935f09cf34dSArchibald Elliott     case 0x27: // 32 nm Atom Medfield
936f09cf34dSArchibald Elliott     case 0x35: // 32 nm Atom Midview
937f09cf34dSArchibald Elliott     case 0x36: // 32 nm Atom Midview
938f09cf34dSArchibald Elliott       CPU = "bonnell";
939f09cf34dSArchibald Elliott       *Type = X86::INTEL_BONNELL;
940f09cf34dSArchibald Elliott       break;
941f09cf34dSArchibald Elliott 
942f09cf34dSArchibald Elliott     // Atom Silvermont codes from the Intel software optimization guide.
943f09cf34dSArchibald Elliott     case 0x37:
944f09cf34dSArchibald Elliott     case 0x4a:
945f09cf34dSArchibald Elliott     case 0x4d:
946f09cf34dSArchibald Elliott     case 0x5a:
947f09cf34dSArchibald Elliott     case 0x5d:
948f09cf34dSArchibald Elliott     case 0x4c: // really airmont
949f09cf34dSArchibald Elliott       CPU = "silvermont";
950f09cf34dSArchibald Elliott       *Type = X86::INTEL_SILVERMONT;
951f09cf34dSArchibald Elliott       break;
952f09cf34dSArchibald Elliott     // Goldmont:
953f09cf34dSArchibald Elliott     case 0x5c: // Apollo Lake
954f09cf34dSArchibald Elliott     case 0x5f: // Denverton
955f09cf34dSArchibald Elliott       CPU = "goldmont";
956f09cf34dSArchibald Elliott       *Type = X86::INTEL_GOLDMONT;
957f09cf34dSArchibald Elliott       break;
958f09cf34dSArchibald Elliott     case 0x7a:
959f09cf34dSArchibald Elliott       CPU = "goldmont-plus";
960f09cf34dSArchibald Elliott       *Type = X86::INTEL_GOLDMONT_PLUS;
961f09cf34dSArchibald Elliott       break;
962f09cf34dSArchibald Elliott     case 0x86:
963e972bdbaSlibenc     case 0x8a: // Lakefield
964e972bdbaSlibenc     case 0x96: // Elkhart Lake
965e972bdbaSlibenc     case 0x9c: // Jasper Lake
966f09cf34dSArchibald Elliott       CPU = "tremont";
967f09cf34dSArchibald Elliott       *Type = X86::INTEL_TREMONT;
968f09cf34dSArchibald Elliott       break;
969f09cf34dSArchibald Elliott 
970f09cf34dSArchibald Elliott     // Sierraforest:
971f09cf34dSArchibald Elliott     case 0xaf:
972f09cf34dSArchibald Elliott       CPU = "sierraforest";
973f09cf34dSArchibald Elliott       *Type = X86::INTEL_SIERRAFOREST;
974f09cf34dSArchibald Elliott       break;
975f09cf34dSArchibald Elliott 
976f09cf34dSArchibald Elliott     // Grandridge:
977f09cf34dSArchibald Elliott     case 0xb6:
978f09cf34dSArchibald Elliott       CPU = "grandridge";
979f09cf34dSArchibald Elliott       *Type = X86::INTEL_GRANDRIDGE;
980f09cf34dSArchibald Elliott       break;
981f09cf34dSArchibald Elliott 
982278e533eSFreddy Ye     // Clearwaterforest:
983278e533eSFreddy Ye     case 0xdd:
984278e533eSFreddy Ye       CPU = "clearwaterforest";
985278e533eSFreddy Ye       *Type = X86::INTEL_CLEARWATERFOREST;
986278e533eSFreddy Ye       break;
987278e533eSFreddy Ye 
988f09cf34dSArchibald Elliott     // Xeon Phi (Knights Landing + Knights Mill):
989f09cf34dSArchibald Elliott     case 0x57:
990f09cf34dSArchibald Elliott       CPU = "knl";
991f09cf34dSArchibald Elliott       *Type = X86::INTEL_KNL;
992f09cf34dSArchibald Elliott       break;
993f09cf34dSArchibald Elliott     case 0x85:
994f09cf34dSArchibald Elliott       CPU = "knm";
995f09cf34dSArchibald Elliott       *Type = X86::INTEL_KNM;
996f09cf34dSArchibald Elliott       break;
997f09cf34dSArchibald Elliott 
998f09cf34dSArchibald Elliott     default: // Unknown family 6 CPU, try to guess.
999f09cf34dSArchibald Elliott       // Don't both with Type/Subtype here, they aren't used by the caller.
1000f09cf34dSArchibald Elliott       // They're used above to keep the code in sync with compiler-rt.
1001f09cf34dSArchibald Elliott       // TODO detect tigerlake host from model
1002f09cf34dSArchibald Elliott       if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {
1003f09cf34dSArchibald Elliott         CPU = "tigerlake";
1004f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512VBMI2)) {
1005f09cf34dSArchibald Elliott         CPU = "icelake-client";
1006f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512VBMI)) {
1007f09cf34dSArchibald Elliott         CPU = "cannonlake";
1008f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512BF16)) {
1009f09cf34dSArchibald Elliott         CPU = "cooperlake";
1010f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
1011f09cf34dSArchibald Elliott         CPU = "cascadelake";
1012f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX512VL)) {
1013f09cf34dSArchibald Elliott         CPU = "skylake-avx512";
1014f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {
1015f09cf34dSArchibald Elliott         if (testFeature(X86::FEATURE_SHA))
1016f09cf34dSArchibald Elliott           CPU = "goldmont";
1017f09cf34dSArchibald Elliott         else
1018f09cf34dSArchibald Elliott           CPU = "skylake";
1019f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_ADX)) {
1020f09cf34dSArchibald Elliott         CPU = "broadwell";
1021f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX2)) {
1022f09cf34dSArchibald Elliott         CPU = "haswell";
1023f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_AVX)) {
1024f09cf34dSArchibald Elliott         CPU = "sandybridge";
1025f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSE4_2)) {
1026f09cf34dSArchibald Elliott         if (testFeature(X86::FEATURE_MOVBE))
1027f09cf34dSArchibald Elliott           CPU = "silvermont";
1028f09cf34dSArchibald Elliott         else
1029f09cf34dSArchibald Elliott           CPU = "nehalem";
1030f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSE4_1)) {
1031f09cf34dSArchibald Elliott         CPU = "penryn";
1032f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSSE3)) {
1033f09cf34dSArchibald Elliott         if (testFeature(X86::FEATURE_MOVBE))
1034f09cf34dSArchibald Elliott           CPU = "bonnell";
1035f09cf34dSArchibald Elliott         else
1036f09cf34dSArchibald Elliott           CPU = "core2";
1037f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_64BIT)) {
1038f09cf34dSArchibald Elliott         CPU = "core2";
1039f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSE3)) {
1040f09cf34dSArchibald Elliott         CPU = "yonah";
1041f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSE2)) {
1042f09cf34dSArchibald Elliott         CPU = "pentium-m";
1043f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_SSE)) {
1044f09cf34dSArchibald Elliott         CPU = "pentium3";
1045f09cf34dSArchibald Elliott       } else if (testFeature(X86::FEATURE_MMX)) {
1046f09cf34dSArchibald Elliott         CPU = "pentium2";
1047f09cf34dSArchibald Elliott       } else {
1048f09cf34dSArchibald Elliott         CPU = "pentiumpro";
1049f09cf34dSArchibald Elliott       }
1050f09cf34dSArchibald Elliott       break;
1051f09cf34dSArchibald Elliott     }
1052f09cf34dSArchibald Elliott     break;
1053f09cf34dSArchibald Elliott   case 15: {
1054f09cf34dSArchibald Elliott     if (testFeature(X86::FEATURE_64BIT)) {
1055f09cf34dSArchibald Elliott       CPU = "nocona";
1056f09cf34dSArchibald Elliott       break;
1057f09cf34dSArchibald Elliott     }
1058f09cf34dSArchibald Elliott     if (testFeature(X86::FEATURE_SSE3)) {
1059f09cf34dSArchibald Elliott       CPU = "prescott";
1060f09cf34dSArchibald Elliott       break;
1061f09cf34dSArchibald Elliott     }
1062f09cf34dSArchibald Elliott     CPU = "pentium4";
1063f09cf34dSArchibald Elliott     break;
1064f09cf34dSArchibald Elliott   }
106597836bedSFreddy Ye   case 19:
106697836bedSFreddy Ye     switch (Model) {
106797836bedSFreddy Ye     // Diamond Rapids:
106897836bedSFreddy Ye     case 0x01:
106997836bedSFreddy Ye       CPU = "diamondrapids";
107097836bedSFreddy Ye       *Type = X86::INTEL_COREI7;
107197836bedSFreddy Ye       *Subtype = X86::INTEL_COREI7_DIAMONDRAPIDS;
107297836bedSFreddy Ye       break;
107397836bedSFreddy Ye 
107497836bedSFreddy Ye     default: // Unknown family 19 CPU.
107597836bedSFreddy Ye       break;
107697836bedSFreddy Ye     }
107797836bedSFreddy Ye     break;
1078f09cf34dSArchibald Elliott   default:
1079f09cf34dSArchibald Elliott     break; // Unknown.
1080f09cf34dSArchibald Elliott   }
1081f09cf34dSArchibald Elliott 
1082f09cf34dSArchibald Elliott   return CPU;
1083f09cf34dSArchibald Elliott }
1084f09cf34dSArchibald Elliott 
108587e914dbSAiden Grossman static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
108687e914dbSAiden Grossman                                                  unsigned Model,
1087f09cf34dSArchibald Elliott                                                  const unsigned *Features,
108887e914dbSAiden Grossman                                                  unsigned *Type,
108987e914dbSAiden Grossman                                                  unsigned *Subtype) {
109087e914dbSAiden Grossman   const char *CPU = 0;
1091f09cf34dSArchibald Elliott 
1092f09cf34dSArchibald Elliott   switch (Family) {
1093f09cf34dSArchibald Elliott   case 4:
1094f09cf34dSArchibald Elliott     CPU = "i486";
1095f09cf34dSArchibald Elliott     break;
1096f09cf34dSArchibald Elliott   case 5:
1097f09cf34dSArchibald Elliott     CPU = "pentium";
1098f09cf34dSArchibald Elliott     switch (Model) {
1099f09cf34dSArchibald Elliott     case 6:
1100f09cf34dSArchibald Elliott     case 7:
1101f09cf34dSArchibald Elliott       CPU = "k6";
1102f09cf34dSArchibald Elliott       break;
1103f09cf34dSArchibald Elliott     case 8:
1104f09cf34dSArchibald Elliott       CPU = "k6-2";
1105f09cf34dSArchibald Elliott       break;
1106f09cf34dSArchibald Elliott     case 9:
1107f09cf34dSArchibald Elliott     case 13:
1108f09cf34dSArchibald Elliott       CPU = "k6-3";
1109f09cf34dSArchibald Elliott       break;
1110f09cf34dSArchibald Elliott     case 10:
1111f09cf34dSArchibald Elliott       CPU = "geode";
1112f09cf34dSArchibald Elliott       break;
1113f09cf34dSArchibald Elliott     }
1114f09cf34dSArchibald Elliott     break;
1115f09cf34dSArchibald Elliott   case 6:
1116f09cf34dSArchibald Elliott     if (testFeature(X86::FEATURE_SSE)) {
1117f09cf34dSArchibald Elliott       CPU = "athlon-xp";
1118f09cf34dSArchibald Elliott       break;
1119f09cf34dSArchibald Elliott     }
1120f09cf34dSArchibald Elliott     CPU = "athlon";
1121f09cf34dSArchibald Elliott     break;
1122f09cf34dSArchibald Elliott   case 15:
1123f09cf34dSArchibald Elliott     if (testFeature(X86::FEATURE_SSE3)) {
1124f09cf34dSArchibald Elliott       CPU = "k8-sse3";
1125f09cf34dSArchibald Elliott       break;
1126f09cf34dSArchibald Elliott     }
1127f09cf34dSArchibald Elliott     CPU = "k8";
1128f09cf34dSArchibald Elliott     break;
1129f09cf34dSArchibald Elliott   case 16:
1130c5f7a323SRipleyTom   case 18:
1131f09cf34dSArchibald Elliott     CPU = "amdfam10";
1132f09cf34dSArchibald Elliott     *Type = X86::AMDFAM10H; // "amdfam10"
1133f09cf34dSArchibald Elliott     switch (Model) {
1134f09cf34dSArchibald Elliott     case 2:
1135f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM10H_BARCELONA;
1136f09cf34dSArchibald Elliott       break;
1137f09cf34dSArchibald Elliott     case 4:
1138f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM10H_SHANGHAI;
1139f09cf34dSArchibald Elliott       break;
1140f09cf34dSArchibald Elliott     case 8:
1141f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM10H_ISTANBUL;
1142f09cf34dSArchibald Elliott       break;
1143f09cf34dSArchibald Elliott     }
1144f09cf34dSArchibald Elliott     break;
1145f09cf34dSArchibald Elliott   case 20:
1146f09cf34dSArchibald Elliott     CPU = "btver1";
1147f09cf34dSArchibald Elliott     *Type = X86::AMD_BTVER1;
1148f09cf34dSArchibald Elliott     break;
1149f09cf34dSArchibald Elliott   case 21:
1150f09cf34dSArchibald Elliott     CPU = "bdver1";
1151f09cf34dSArchibald Elliott     *Type = X86::AMDFAM15H;
1152f09cf34dSArchibald Elliott     if (Model >= 0x60 && Model <= 0x7f) {
1153f09cf34dSArchibald Elliott       CPU = "bdver4";
1154f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM15H_BDVER4;
1155f09cf34dSArchibald Elliott       break; // 60h-7Fh: Excavator
1156f09cf34dSArchibald Elliott     }
1157f09cf34dSArchibald Elliott     if (Model >= 0x30 && Model <= 0x3f) {
1158f09cf34dSArchibald Elliott       CPU = "bdver3";
1159f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM15H_BDVER3;
1160f09cf34dSArchibald Elliott       break; // 30h-3Fh: Steamroller
1161f09cf34dSArchibald Elliott     }
1162f09cf34dSArchibald Elliott     if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
1163f09cf34dSArchibald Elliott       CPU = "bdver2";
1164f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM15H_BDVER2;
1165f09cf34dSArchibald Elliott       break; // 02h, 10h-1Fh: Piledriver
1166f09cf34dSArchibald Elliott     }
1167f09cf34dSArchibald Elliott     if (Model <= 0x0f) {
1168f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM15H_BDVER1;
1169f09cf34dSArchibald Elliott       break; // 00h-0Fh: Bulldozer
1170f09cf34dSArchibald Elliott     }
1171f09cf34dSArchibald Elliott     break;
1172f09cf34dSArchibald Elliott   case 22:
1173f09cf34dSArchibald Elliott     CPU = "btver2";
1174f09cf34dSArchibald Elliott     *Type = X86::AMD_BTVER2;
1175f09cf34dSArchibald Elliott     break;
1176f09cf34dSArchibald Elliott   case 23:
1177f09cf34dSArchibald Elliott     CPU = "znver1";
1178f09cf34dSArchibald Elliott     *Type = X86::AMDFAM17H;
1179a15532d7SAiden Grossman     if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||
1180a15532d7SAiden Grossman         (Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) ||
1181a15532d7SAiden Grossman         (Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) ||
1182a15532d7SAiden Grossman         (Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) ||
1183a15532d7SAiden Grossman         (Model >= 0xa0 && Model <= 0xaf)) {
1184a15532d7SAiden Grossman       // Family 17h Models 30h-3Fh (Starship) Zen 2
1185a15532d7SAiden Grossman       // Family 17h Models 47h (Cardinal) Zen 2
1186a15532d7SAiden Grossman       // Family 17h Models 60h-67h (Renoir) Zen 2
1187a15532d7SAiden Grossman       // Family 17h Models 68h-6Fh (Lucienne) Zen 2
1188a15532d7SAiden Grossman       // Family 17h Models 70h-7Fh (Matisse) Zen 2
1189a15532d7SAiden Grossman       // Family 17h Models 84h-87h (ProjectX) Zen 2
1190a15532d7SAiden Grossman       // Family 17h Models 90h-97h (VanGogh) Zen 2
1191a15532d7SAiden Grossman       // Family 17h Models 98h-9Fh (Mero) Zen 2
1192a15532d7SAiden Grossman       // Family 17h Models A0h-AFh (Mendocino) Zen 2
1193f09cf34dSArchibald Elliott       CPU = "znver2";
1194f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM17H_ZNVER2;
1195a15532d7SAiden Grossman       break;
1196f09cf34dSArchibald Elliott     }
1197a15532d7SAiden Grossman     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) {
1198a15532d7SAiden Grossman       // Family 17h Models 10h-1Fh (Raven1) Zen
1199a15532d7SAiden Grossman       // Family 17h Models 10h-1Fh (Picasso) Zen+
1200a15532d7SAiden Grossman       // Family 17h Models 20h-2Fh (Raven2 x86) Zen
1201f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM17H_ZNVER1;
1202a15532d7SAiden Grossman       break;
1203f09cf34dSArchibald Elliott     }
1204f09cf34dSArchibald Elliott     break;
1205f09cf34dSArchibald Elliott   case 25:
1206f09cf34dSArchibald Elliott     CPU = "znver3";
1207f09cf34dSArchibald Elliott     *Type = X86::AMDFAM19H;
12083ddf3685SAiden Grossman     if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||
1209a15532d7SAiden Grossman         (Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||
1210a15532d7SAiden Grossman         (Model >= 0x50 && Model <= 0x5f)) {
1211a15532d7SAiden Grossman       // Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3
1212a15532d7SAiden Grossman       // Family 19h Models 20h-2Fh (Vermeer) Zen 3
1213a15532d7SAiden Grossman       // Family 19h Models 30h-3Fh (Badami) Zen 3
1214a15532d7SAiden Grossman       // Family 19h Models 40h-4Fh (Rembrandt) Zen 3+
1215a15532d7SAiden Grossman       // Family 19h Models 50h-5Fh (Cezanne) Zen 3
1216f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM19H_ZNVER3;
1217f09cf34dSArchibald Elliott       break;
1218f09cf34dSArchibald Elliott     }
1219a15532d7SAiden Grossman     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) ||
1220a15532d7SAiden Grossman         (Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) ||
1221a15532d7SAiden Grossman         (Model >= 0xa0 && Model <= 0xaf)) {
1222a15532d7SAiden Grossman       // Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 4
1223a15532d7SAiden Grossman       // Family 19h Models 60h-6Fh (Raphael) Zen 4
1224a15532d7SAiden Grossman       // Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 4
1225a15532d7SAiden Grossman       // Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 4
1226a15532d7SAiden Grossman       // Family 19h Models A0h-AFh (Stones-Dense) Zen 4
1227f09cf34dSArchibald Elliott       CPU = "znver4";
1228f09cf34dSArchibald Elliott       *Subtype = X86::AMDFAM19H_ZNVER4;
1229f09cf34dSArchibald Elliott       break; //  "znver4"
1230f09cf34dSArchibald Elliott     }
123187e914dbSAiden Grossman     break; // family 19h
123202e4186dSGanesh   case 26:
123302e4186dSGanesh     CPU = "znver5";
123402e4186dSGanesh     *Type = X86::AMDFAM1AH;
123502e4186dSGanesh     if (Model <= 0x77) {
123602e4186dSGanesh       // Models 00h-0Fh (Breithorn).
123702e4186dSGanesh       // Models 10h-1Fh (Breithorn-Dense).
123802e4186dSGanesh       // Models 20h-2Fh (Strix 1).
123902e4186dSGanesh       // Models 30h-37h (Strix 2).
124002e4186dSGanesh       // Models 38h-3Fh (Strix 3).
124102e4186dSGanesh       // Models 40h-4Fh (Granite Ridge).
124202e4186dSGanesh       // Models 50h-5Fh (Weisshorn).
124302e4186dSGanesh       // Models 60h-6Fh (Krackan1).
124402e4186dSGanesh       // Models 70h-77h (Sarlak).
124502e4186dSGanesh       CPU = "znver5";
124602e4186dSGanesh       *Subtype = X86::AMDFAM1AH_ZNVER5;
124702e4186dSGanesh       break; //  "znver5"
124802e4186dSGanesh     }
124902e4186dSGanesh     break;
125002e4186dSGanesh 
1251f09cf34dSArchibald Elliott   default:
1252f09cf34dSArchibald Elliott     break; // Unknown AMD CPU.
1253f09cf34dSArchibald Elliott   }
1254f09cf34dSArchibald Elliott 
1255f09cf34dSArchibald Elliott   return CPU;
1256f09cf34dSArchibald Elliott }
1257f09cf34dSArchibald Elliott 
12583f9bff3dSHaojian Wu #undef testFeature
125987e914dbSAiden Grossman 
1260f09cf34dSArchibald Elliott static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
1261f09cf34dSArchibald Elliott                                  unsigned *Features) {
1262f09cf34dSArchibald Elliott   unsigned EAX, EBX;
1263f09cf34dSArchibald Elliott 
1264f09cf34dSArchibald Elliott   auto setFeature = [&](unsigned F) {
1265f09cf34dSArchibald Elliott     Features[F / 32] |= 1U << (F % 32);
1266f09cf34dSArchibald Elliott   };
1267f09cf34dSArchibald Elliott 
1268f09cf34dSArchibald Elliott   if ((EDX >> 15) & 1)
1269f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_CMOV);
1270f09cf34dSArchibald Elliott   if ((EDX >> 23) & 1)
1271f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_MMX);
1272f09cf34dSArchibald Elliott   if ((EDX >> 25) & 1)
1273f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE);
1274f09cf34dSArchibald Elliott   if ((EDX >> 26) & 1)
1275f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE2);
1276f09cf34dSArchibald Elliott 
1277f09cf34dSArchibald Elliott   if ((ECX >> 0) & 1)
1278f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE3);
1279f09cf34dSArchibald Elliott   if ((ECX >> 1) & 1)
1280f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_PCLMUL);
1281f09cf34dSArchibald Elliott   if ((ECX >> 9) & 1)
1282f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSSE3);
1283f09cf34dSArchibald Elliott   if ((ECX >> 12) & 1)
1284f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_FMA);
1285f09cf34dSArchibald Elliott   if ((ECX >> 19) & 1)
1286f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE4_1);
1287f09cf34dSArchibald Elliott   if ((ECX >> 20) & 1) {
1288f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE4_2);
1289f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_CRC32);
1290f09cf34dSArchibald Elliott   }
1291f09cf34dSArchibald Elliott   if ((ECX >> 23) & 1)
1292f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_POPCNT);
1293f09cf34dSArchibald Elliott   if ((ECX >> 25) & 1)
1294f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AES);
1295f09cf34dSArchibald Elliott 
1296f09cf34dSArchibald Elliott   if ((ECX >> 22) & 1)
1297f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_MOVBE);
1298f09cf34dSArchibald Elliott 
1299f09cf34dSArchibald Elliott   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1300f09cf34dSArchibald Elliott   // indicates that the AVX registers will be saved and restored on context
1301f09cf34dSArchibald Elliott   // switch, then we have full AVX support.
1302f09cf34dSArchibald Elliott   const unsigned AVXBits = (1 << 27) | (1 << 28);
1303f09cf34dSArchibald Elliott   bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
1304f09cf34dSArchibald Elliott                 ((EAX & 0x6) == 0x6);
1305f09cf34dSArchibald Elliott #if defined(__APPLE__)
1306f09cf34dSArchibald Elliott   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1307f09cf34dSArchibald Elliott   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1308f09cf34dSArchibald Elliott   // set right now.
1309f09cf34dSArchibald Elliott   bool HasAVX512Save = true;
1310f09cf34dSArchibald Elliott #else
1311f09cf34dSArchibald Elliott   // AVX512 requires additional context to be saved by the OS.
1312f09cf34dSArchibald Elliott   bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
1313f09cf34dSArchibald Elliott #endif
1314f09cf34dSArchibald Elliott 
1315f09cf34dSArchibald Elliott   if (HasAVX)
1316f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX);
1317f09cf34dSArchibald Elliott 
1318f09cf34dSArchibald Elliott   bool HasLeaf7 =
1319f09cf34dSArchibald Elliott       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1320f09cf34dSArchibald Elliott 
1321f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 3) & 1))
1322f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_BMI);
1323f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
1324f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX2);
1325f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 8) & 1))
1326f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_BMI2);
1327b3291793SPhoebe Wang   if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) {
1328f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512F);
1329b3291793SPhoebe Wang     setFeature(X86::FEATURE_EVEX512);
1330b3291793SPhoebe Wang   }
1331f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
1332f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512DQ);
1333f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 19) & 1))
1334f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_ADX);
1335f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
1336f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512IFMA);
1337f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 23) & 1))
1338f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_CLFLUSHOPT);
1339f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
1340f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512CD);
1341f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 29) & 1))
1342f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SHA);
1343f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
1344f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512BW);
1345f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
1346f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VL);
1347f09cf34dSArchibald Elliott 
1348f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
1349f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VBMI);
1350f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
1351f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VBMI2);
1352f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 8) & 1))
1353f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_GFNI);
1354f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
1355f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_VPCLMULQDQ);
1356f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
1357f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VNNI);
1358f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
1359f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512BITALG);
1360f09cf34dSArchibald Elliott   if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
1361f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
1362f09cf34dSArchibald Elliott 
1363f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
1364f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX5124VNNIW);
1365f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
1366f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX5124FMAPS);
1367f09cf34dSArchibald Elliott   if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
1368f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512VP2INTERSECT);
1369f09cf34dSArchibald Elliott 
13702a5e3f4cSCraig Topper   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
13712a5e3f4cSCraig Topper   // return all 0s for invalid subleaves so check the limit.
1372f09cf34dSArchibald Elliott   bool HasLeaf7Subleaf1 =
13732a5e3f4cSCraig Topper       HasLeaf7 && EAX >= 1 &&
13742a5e3f4cSCraig Topper       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1375f09cf34dSArchibald Elliott   if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
1376f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_AVX512BF16);
1377f09cf34dSArchibald Elliott 
1378f09cf34dSArchibald Elliott   unsigned MaxExtLevel;
1379f09cf34dSArchibald Elliott   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1380f09cf34dSArchibald Elliott 
1381f09cf34dSArchibald Elliott   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1382f09cf34dSArchibald Elliott                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1383f09cf34dSArchibald Elliott   if (HasExtLeaf1 && ((ECX >> 6) & 1))
1384f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_SSE4_A);
1385f09cf34dSArchibald Elliott   if (HasExtLeaf1 && ((ECX >> 11) & 1))
1386f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_XOP);
1387f09cf34dSArchibald Elliott   if (HasExtLeaf1 && ((ECX >> 16) & 1))
1388f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_FMA4);
1389f09cf34dSArchibald Elliott 
1390f09cf34dSArchibald Elliott   if (HasExtLeaf1 && ((EDX >> 29) & 1))
1391f09cf34dSArchibald Elliott     setFeature(X86::FEATURE_64BIT);
1392f09cf34dSArchibald Elliott }
1393f09cf34dSArchibald Elliott 
1394f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1395f09cf34dSArchibald Elliott   unsigned MaxLeaf = 0;
1396f09cf34dSArchibald Elliott   const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);
1397f09cf34dSArchibald Elliott   if (Vendor == VendorSignatures::UNKNOWN)
1398f09cf34dSArchibald Elliott     return "generic";
1399f09cf34dSArchibald Elliott 
1400f09cf34dSArchibald Elliott   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1401f09cf34dSArchibald Elliott   getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
1402f09cf34dSArchibald Elliott 
1403f09cf34dSArchibald Elliott   unsigned Family = 0, Model = 0;
1404f09cf34dSArchibald Elliott   unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};
1405f09cf34dSArchibald Elliott   detectX86FamilyModel(EAX, &Family, &Model);
1406f09cf34dSArchibald Elliott   getAvailableFeatures(ECX, EDX, MaxLeaf, Features);
1407f09cf34dSArchibald Elliott 
1408f09cf34dSArchibald Elliott   // These aren't consumed in this file, but we try to keep some source code the
1409f09cf34dSArchibald Elliott   // same or similar to compiler-rt.
1410f09cf34dSArchibald Elliott   unsigned Type = 0;
1411f09cf34dSArchibald Elliott   unsigned Subtype = 0;
1412f09cf34dSArchibald Elliott 
1413f09cf34dSArchibald Elliott   StringRef CPU;
1414f09cf34dSArchibald Elliott 
1415f09cf34dSArchibald Elliott   if (Vendor == VendorSignatures::GENUINE_INTEL) {
1416f09cf34dSArchibald Elliott     CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,
1417f09cf34dSArchibald Elliott                                           &Subtype);
1418f09cf34dSArchibald Elliott   } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {
1419f09cf34dSArchibald Elliott     CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,
1420f09cf34dSArchibald Elliott                                         &Subtype);
1421f09cf34dSArchibald Elliott   }
1422f09cf34dSArchibald Elliott 
1423f09cf34dSArchibald Elliott   if (!CPU.empty())
1424f09cf34dSArchibald Elliott     return CPU;
1425f09cf34dSArchibald Elliott 
1426f09cf34dSArchibald Elliott   return "generic";
1427f09cf34dSArchibald Elliott }
1428f09cf34dSArchibald Elliott 
1429f09cf34dSArchibald Elliott #elif defined(__APPLE__) && defined(__powerpc__)
1430f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1431f09cf34dSArchibald Elliott   host_basic_info_data_t hostInfo;
1432f09cf34dSArchibald Elliott   mach_msg_type_number_t infoCount;
1433f09cf34dSArchibald Elliott 
1434f09cf34dSArchibald Elliott   infoCount = HOST_BASIC_INFO_COUNT;
1435f09cf34dSArchibald Elliott   mach_port_t hostPort = mach_host_self();
1436f09cf34dSArchibald Elliott   host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
1437f09cf34dSArchibald Elliott             &infoCount);
1438f09cf34dSArchibald Elliott   mach_port_deallocate(mach_task_self(), hostPort);
1439f09cf34dSArchibald Elliott 
1440f09cf34dSArchibald Elliott   if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
1441f09cf34dSArchibald Elliott     return "generic";
1442f09cf34dSArchibald Elliott 
1443f09cf34dSArchibald Elliott   switch (hostInfo.cpu_subtype) {
1444f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_601:
1445f09cf34dSArchibald Elliott     return "601";
1446f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_602:
1447f09cf34dSArchibald Elliott     return "602";
1448f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_603:
1449f09cf34dSArchibald Elliott     return "603";
1450f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_603e:
1451f09cf34dSArchibald Elliott     return "603e";
1452f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_603ev:
1453f09cf34dSArchibald Elliott     return "603ev";
1454f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_604:
1455f09cf34dSArchibald Elliott     return "604";
1456f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_604e:
1457f09cf34dSArchibald Elliott     return "604e";
1458f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_620:
1459f09cf34dSArchibald Elliott     return "620";
1460f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_750:
1461f09cf34dSArchibald Elliott     return "750";
1462f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_7400:
1463f09cf34dSArchibald Elliott     return "7400";
1464f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_7450:
1465f09cf34dSArchibald Elliott     return "7450";
1466f09cf34dSArchibald Elliott   case CPU_SUBTYPE_POWERPC_970:
1467f09cf34dSArchibald Elliott     return "970";
1468f09cf34dSArchibald Elliott   default:;
1469f09cf34dSArchibald Elliott   }
1470f09cf34dSArchibald Elliott 
1471f09cf34dSArchibald Elliott   return "generic";
1472f09cf34dSArchibald Elliott }
1473f09cf34dSArchibald Elliott #elif defined(__linux__) && defined(__powerpc__)
1474f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1475f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1476f09cf34dSArchibald Elliott   StringRef Content = P ? P->getBuffer() : "";
1477f09cf34dSArchibald Elliott   return detail::getHostCPUNameForPowerPC(Content);
1478f09cf34dSArchibald Elliott }
1479f09cf34dSArchibald Elliott #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
1480f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1481f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1482f09cf34dSArchibald Elliott   StringRef Content = P ? P->getBuffer() : "";
1483f09cf34dSArchibald Elliott   return detail::getHostCPUNameForARM(Content);
1484f09cf34dSArchibald Elliott }
1485f09cf34dSArchibald Elliott #elif defined(__linux__) && defined(__s390x__)
1486f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1487f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1488f09cf34dSArchibald Elliott   StringRef Content = P ? P->getBuffer() : "";
1489f09cf34dSArchibald Elliott   return detail::getHostCPUNameForS390x(Content);
1490f09cf34dSArchibald Elliott }
1491f09cf34dSArchibald Elliott #elif defined(__MVS__)
1492f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1493f09cf34dSArchibald Elliott   // Get pointer to Communications Vector Table (CVT).
1494f09cf34dSArchibald Elliott   // The pointer is located at offset 16 of the Prefixed Save Area (PSA).
1495f09cf34dSArchibald Elliott   // It is stored as 31 bit pointer and will be zero-extended to 64 bit.
1496f09cf34dSArchibald Elliott   int *StartToCVTOffset = reinterpret_cast<int *>(0x10);
1497f09cf34dSArchibald Elliott   // Since its stored as a 31-bit pointer, get the 4 bytes from the start
1498f09cf34dSArchibald Elliott   // of address.
1499f09cf34dSArchibald Elliott   int ReadValue = *StartToCVTOffset;
1500f09cf34dSArchibald Elliott   // Explicitly clear the high order bit.
1501f09cf34dSArchibald Elliott   ReadValue = (ReadValue & 0x7FFFFFFF);
1502f09cf34dSArchibald Elliott   char *CVT = reinterpret_cast<char *>(ReadValue);
1503f09cf34dSArchibald Elliott   // The model number is located in the CVT prefix at offset -6 and stored as
1504f09cf34dSArchibald Elliott   // signless packed decimal.
1505f09cf34dSArchibald Elliott   uint16_t Id = *(uint16_t *)&CVT[-6];
1506f09cf34dSArchibald Elliott   // Convert number to integer.
1507f09cf34dSArchibald Elliott   Id = decodePackedBCD<uint16_t>(Id, false);
1508f09cf34dSArchibald Elliott   // Check for vector support. It's stored in field CVTFLAG5 (offset 244),
1509f09cf34dSArchibald Elliott   // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector
1510f09cf34dSArchibald Elliott   // extension can only be used if bit CVTVEF is on.
1511f09cf34dSArchibald Elliott   bool HaveVectorSupport = CVT[244] & 0x80;
1512f09cf34dSArchibald Elliott   return getCPUNameFromS390Model(Id, HaveVectorSupport);
1513f09cf34dSArchibald Elliott }
1514f09cf34dSArchibald Elliott #elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
1515a082cc14SMads Marquart // Copied from <mach/machine.h> in the macOS SDK.
1516a082cc14SMads Marquart //
1517a082cc14SMads Marquart // Also available here, though usually not as up-to-date:
1518a082cc14SMads Marquart // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.41.3/osfmk/mach/machine.h#L403-L452.
1519a082cc14SMads Marquart #define CPUFAMILY_UNKNOWN 0
1520a082cc14SMads Marquart #define CPUFAMILY_ARM_9 0xe73283ae
1521a082cc14SMads Marquart #define CPUFAMILY_ARM_11 0x8ff620d8
1522a082cc14SMads Marquart #define CPUFAMILY_ARM_XSCALE 0x53b005f5
1523a082cc14SMads Marquart #define CPUFAMILY_ARM_12 0xbd1b0ae9
1524a082cc14SMads Marquart #define CPUFAMILY_ARM_13 0x0cc90e64
1525a082cc14SMads Marquart #define CPUFAMILY_ARM_14 0x96077ef1
1526a082cc14SMads Marquart #define CPUFAMILY_ARM_15 0xa8511bca
1527f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_SWIFT 0x1e2d6381
1528f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_CYCLONE 0x37a09642
1529f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
1530f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_TWISTER 0x92fb37c8
1531f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_HURRICANE 0x67ceee93
1532f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
1533f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
1534f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
1535f09cf34dSArchibald Elliott #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
153670da9155SMads Marquart #define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d
153770da9155SMads Marquart #define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
1538a082cc14SMads Marquart #define CPUFAMILY_ARM_IBIZA 0xfa33415e
1539a082cc14SMads Marquart #define CPUFAMILY_ARM_PALMA 0x72015832
1540a082cc14SMads Marquart #define CPUFAMILY_ARM_COLL 0x2876f5b5
1541a082cc14SMads Marquart #define CPUFAMILY_ARM_LOBOS 0x5f4dea93
1542a082cc14SMads Marquart #define CPUFAMILY_ARM_DONAN 0x6f5129ac
1543a082cc14SMads Marquart #define CPUFAMILY_ARM_BRAVA 0x17d5b93a
1544a082cc14SMads Marquart #define CPUFAMILY_ARM_TAHITI 0x75d4acb9
1545a082cc14SMads Marquart #define CPUFAMILY_ARM_TUPAI 0x204526d0
1546f09cf34dSArchibald Elliott 
1547f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1548f09cf34dSArchibald Elliott   uint32_t Family;
1549f09cf34dSArchibald Elliott   size_t Length = sizeof(Family);
1550f09cf34dSArchibald Elliott   sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);
1551f09cf34dSArchibald Elliott 
1552a082cc14SMads Marquart   // This is found by testing on actual hardware, and by looking at:
1553a082cc14SMads Marquart   // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.41.3/osfmk/arm/cpuid.c#L109-L231.
1554a082cc14SMads Marquart   //
1555a082cc14SMads Marquart   // Another great resource is
1556a082cc14SMads Marquart   // https://github.com/AsahiLinux/docs/wiki/Codenames.
1557a082cc14SMads Marquart   //
1558a082cc14SMads Marquart   // NOTE: We choose to return `apple-mX` instead of `apple-aX`, since the M1,
1559a082cc14SMads Marquart   // M2, M3 etc. aliases are more widely known to users than A14, A15, A16 etc.
1560a082cc14SMads Marquart   // (and this code is basically only used on host macOS anyways).
1561f09cf34dSArchibald Elliott   switch (Family) {
1562a082cc14SMads Marquart   case CPUFAMILY_UNKNOWN:
1563a082cc14SMads Marquart     return "generic";
1564a082cc14SMads Marquart   case CPUFAMILY_ARM_9:
1565a082cc14SMads Marquart     return "arm920t"; // or arm926ej-s
1566a082cc14SMads Marquart   case CPUFAMILY_ARM_11:
1567a082cc14SMads Marquart     return "arm1136jf-s";
1568a082cc14SMads Marquart   case CPUFAMILY_ARM_XSCALE:
1569a082cc14SMads Marquart     return "xscale";
1570a082cc14SMads Marquart   case CPUFAMILY_ARM_12: // Seems unused by the kernel
1571a082cc14SMads Marquart     return "generic";
1572a082cc14SMads Marquart   case CPUFAMILY_ARM_13:
1573a082cc14SMads Marquart     return "cortex-a8";
1574a082cc14SMads Marquart   case CPUFAMILY_ARM_14:
1575a082cc14SMads Marquart     return "cortex-a9";
1576a082cc14SMads Marquart   case CPUFAMILY_ARM_15:
1577a082cc14SMads Marquart     return "cortex-a7";
1578f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_SWIFT:
1579f09cf34dSArchibald Elliott     return "swift";
1580f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_CYCLONE:
1581f09cf34dSArchibald Elliott     return "apple-a7";
1582f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_TYPHOON:
1583f09cf34dSArchibald Elliott     return "apple-a8";
1584f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_TWISTER:
1585f09cf34dSArchibald Elliott     return "apple-a9";
1586f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_HURRICANE:
1587f09cf34dSArchibald Elliott     return "apple-a10";
1588f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_MONSOON_MISTRAL:
1589f09cf34dSArchibald Elliott     return "apple-a11";
1590f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_VORTEX_TEMPEST:
1591f09cf34dSArchibald Elliott     return "apple-a12";
1592f09cf34dSArchibald Elliott   case CPUFAMILY_ARM_LIGHTNING_THUNDER:
1593f09cf34dSArchibald Elliott     return "apple-a13";
1594a082cc14SMads Marquart   case CPUFAMILY_ARM_FIRESTORM_ICESTORM: // A14 / M1
1595f09cf34dSArchibald Elliott     return "apple-m1";
1596a082cc14SMads Marquart   case CPUFAMILY_ARM_BLIZZARD_AVALANCHE: // A15 / M2
159770da9155SMads Marquart     return "apple-m2";
1598a082cc14SMads Marquart   case CPUFAMILY_ARM_EVEREST_SAWTOOTH: // A16
1599a082cc14SMads Marquart   case CPUFAMILY_ARM_IBIZA:            // M3
1600a082cc14SMads Marquart   case CPUFAMILY_ARM_PALMA:            // M3 Max
1601a082cc14SMads Marquart   case CPUFAMILY_ARM_LOBOS:            // M3 Pro
160270da9155SMads Marquart     return "apple-m3";
1603a082cc14SMads Marquart   case CPUFAMILY_ARM_COLL: // A17 Pro
1604a082cc14SMads Marquart     return "apple-a17";
1605a082cc14SMads Marquart   case CPUFAMILY_ARM_DONAN:  // M4
1606a082cc14SMads Marquart   case CPUFAMILY_ARM_BRAVA:  // M4 Max
1607a082cc14SMads Marquart   case CPUFAMILY_ARM_TAHITI: // A18 Pro
1608a082cc14SMads Marquart   case CPUFAMILY_ARM_TUPAI:  // A18
1609a082cc14SMads Marquart     return "apple-m4";
1610f09cf34dSArchibald Elliott   default:
1611f09cf34dSArchibald Elliott     // Default to the newest CPU we know about.
1612a082cc14SMads Marquart     return "apple-m4";
1613f09cf34dSArchibald Elliott   }
1614f09cf34dSArchibald Elliott }
1615f09cf34dSArchibald Elliott #elif defined(_AIX)
1616f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1617f09cf34dSArchibald Elliott   switch (_system_configuration.implementation) {
1618f09cf34dSArchibald Elliott   case POWER_4:
1619f09cf34dSArchibald Elliott     if (_system_configuration.version == PV_4_3)
1620f09cf34dSArchibald Elliott       return "970";
1621f09cf34dSArchibald Elliott     return "pwr4";
1622f09cf34dSArchibald Elliott   case POWER_5:
1623f09cf34dSArchibald Elliott     if (_system_configuration.version == PV_5)
1624f09cf34dSArchibald Elliott       return "pwr5";
1625f09cf34dSArchibald Elliott     return "pwr5x";
1626f09cf34dSArchibald Elliott   case POWER_6:
1627f09cf34dSArchibald Elliott     if (_system_configuration.version == PV_6_Compat)
1628f09cf34dSArchibald Elliott       return "pwr6";
1629f09cf34dSArchibald Elliott     return "pwr6x";
1630f09cf34dSArchibald Elliott   case POWER_7:
1631f09cf34dSArchibald Elliott     return "pwr7";
1632f09cf34dSArchibald Elliott   case POWER_8:
1633f09cf34dSArchibald Elliott     return "pwr8";
1634f09cf34dSArchibald Elliott   case POWER_9:
1635f09cf34dSArchibald Elliott     return "pwr9";
1636f09cf34dSArchibald Elliott // TODO: simplify this once the macro is available in all OS levels.
1637f09cf34dSArchibald Elliott #ifdef POWER_10
1638f09cf34dSArchibald Elliott   case POWER_10:
1639f09cf34dSArchibald Elliott #else
1640f09cf34dSArchibald Elliott   case 0x40000:
1641f09cf34dSArchibald Elliott #endif
1642f09cf34dSArchibald Elliott     return "pwr10";
16431df4d866Sazhan92 #ifdef POWER_11
16441df4d866Sazhan92   case POWER_11:
16451df4d866Sazhan92 #else
16461df4d866Sazhan92   case 0x80000:
16471df4d866Sazhan92 #endif
16481df4d866Sazhan92     return "pwr11";
1649f09cf34dSArchibald Elliott   default:
1650f09cf34dSArchibald Elliott     return "generic";
1651f09cf34dSArchibald Elliott   }
1652f09cf34dSArchibald Elliott }
1653e53f41c3Swanglei #elif defined(__loongarch__)
1654e53f41c3Swanglei StringRef sys::getHostCPUName() {
1655e53f41c3Swanglei   // Use processor id to detect cpu name.
1656e53f41c3Swanglei   uint32_t processor_id;
1657e53f41c3Swanglei   __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));
16587e186d36SWeining Lu   // Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h.
16597e186d36SWeining Lu   switch (processor_id & 0xf000) {
1660e53f41c3Swanglei   case 0xc000: // Loongson 64bit, 4-issue
1661e53f41c3Swanglei     return "la464";
1662fcec2980SAmi-zhang   case 0xd000: // Loongson 64bit, 6-issue
1663fcec2980SAmi-zhang     return "la664";
1664e53f41c3Swanglei   // TODO: Others.
1665e53f41c3Swanglei   default:
1666e53f41c3Swanglei     break;
1667e53f41c3Swanglei   }
1668e53f41c3Swanglei   return "generic";
1669e53f41c3Swanglei }
1670f09cf34dSArchibald Elliott #elif defined(__riscv)
1671f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1672f09cf34dSArchibald Elliott #if defined(__linux__)
1673f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1674f09cf34dSArchibald Elliott   StringRef Content = P ? P->getBuffer() : "";
1675578cf724SYingwei Zheng   StringRef Name = detail::getHostCPUNameForRISCV(Content);
1676578cf724SYingwei Zheng   if (!Name.empty())
1677578cf724SYingwei Zheng     return Name;
1678578cf724SYingwei Zheng #endif
1679f09cf34dSArchibald Elliott #if __riscv_xlen == 64
1680f09cf34dSArchibald Elliott   return "generic-rv64";
1681f09cf34dSArchibald Elliott #elif __riscv_xlen == 32
1682f09cf34dSArchibald Elliott   return "generic-rv32";
1683f09cf34dSArchibald Elliott #else
1684f09cf34dSArchibald Elliott #error "Unhandled value of __riscv_xlen"
1685f09cf34dSArchibald Elliott #endif
1686f09cf34dSArchibald Elliott }
1687f09cf34dSArchibald Elliott #elif defined(__sparc__)
1688f09cf34dSArchibald Elliott #if defined(__linux__)
1689f09cf34dSArchibald Elliott StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {
1690f09cf34dSArchibald Elliott   SmallVector<StringRef> Lines;
1691fd38a955SCraig Topper   ProcCpuinfoContent.split(Lines, '\n');
1692f09cf34dSArchibald Elliott 
1693f09cf34dSArchibald Elliott   // Look for cpu line to determine cpu name
1694f09cf34dSArchibald Elliott   StringRef Cpu;
1695f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
1696038871aeSKazu Hirata     if (Lines[I].starts_with("cpu")) {
1697f09cf34dSArchibald Elliott       Cpu = Lines[I].substr(5).ltrim("\t :");
1698f09cf34dSArchibald Elliott       break;
1699f09cf34dSArchibald Elliott     }
1700f09cf34dSArchibald Elliott   }
1701f09cf34dSArchibald Elliott 
1702f09cf34dSArchibald Elliott   return StringSwitch<const char *>(Cpu)
1703f09cf34dSArchibald Elliott       .StartsWith("SuperSparc", "supersparc")
1704f09cf34dSArchibald Elliott       .StartsWith("HyperSparc", "hypersparc")
1705f09cf34dSArchibald Elliott       .StartsWith("SpitFire", "ultrasparc")
1706f09cf34dSArchibald Elliott       .StartsWith("BlackBird", "ultrasparc")
1707f09cf34dSArchibald Elliott       .StartsWith("Sabre", " ultrasparc")
1708f09cf34dSArchibald Elliott       .StartsWith("Hummingbird", "ultrasparc")
1709f09cf34dSArchibald Elliott       .StartsWith("Cheetah", "ultrasparc3")
1710f09cf34dSArchibald Elliott       .StartsWith("Jalapeno", "ultrasparc3")
1711f09cf34dSArchibald Elliott       .StartsWith("Jaguar", "ultrasparc3")
1712f09cf34dSArchibald Elliott       .StartsWith("Panther", "ultrasparc3")
1713f09cf34dSArchibald Elliott       .StartsWith("Serrano", "ultrasparc3")
1714f09cf34dSArchibald Elliott       .StartsWith("UltraSparc T1", "niagara")
1715f09cf34dSArchibald Elliott       .StartsWith("UltraSparc T2", "niagara2")
1716f09cf34dSArchibald Elliott       .StartsWith("UltraSparc T3", "niagara3")
1717f09cf34dSArchibald Elliott       .StartsWith("UltraSparc T4", "niagara4")
1718f09cf34dSArchibald Elliott       .StartsWith("UltraSparc T5", "niagara4")
1719f09cf34dSArchibald Elliott       .StartsWith("LEON", "leon3")
1720f09cf34dSArchibald Elliott       // niagara7/m8 not supported by LLVM yet.
1721f09cf34dSArchibald Elliott       .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)
1722f09cf34dSArchibald Elliott       .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)
1723f09cf34dSArchibald Elliott       .StartsWith("SPARC-M8", "niagara4" /* "m8" */)
1724f09cf34dSArchibald Elliott       .Default("generic");
1725f09cf34dSArchibald Elliott }
1726f09cf34dSArchibald Elliott #endif
1727f09cf34dSArchibald Elliott 
1728f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() {
1729f09cf34dSArchibald Elliott #if defined(__linux__)
1730f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1731f09cf34dSArchibald Elliott   StringRef Content = P ? P->getBuffer() : "";
1732f09cf34dSArchibald Elliott   return detail::getHostCPUNameForSPARC(Content);
1733f09cf34dSArchibald Elliott #elif defined(__sun__) && defined(__svr4__)
1734f09cf34dSArchibald Elliott   char *buf = NULL;
1735f09cf34dSArchibald Elliott   kstat_ctl_t *kc;
1736f09cf34dSArchibald Elliott   kstat_t *ksp;
1737f09cf34dSArchibald Elliott   kstat_named_t *brand = NULL;
1738f09cf34dSArchibald Elliott 
1739f09cf34dSArchibald Elliott   kc = kstat_open();
1740f09cf34dSArchibald Elliott   if (kc != NULL) {
1741f09cf34dSArchibald Elliott     ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);
1742f09cf34dSArchibald Elliott     if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&
1743f09cf34dSArchibald Elliott         ksp->ks_type == KSTAT_TYPE_NAMED)
1744f09cf34dSArchibald Elliott       brand =
1745f09cf34dSArchibald Elliott           (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));
1746f09cf34dSArchibald Elliott     if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
1747f09cf34dSArchibald Elliott       buf = KSTAT_NAMED_STR_PTR(brand);
1748f09cf34dSArchibald Elliott   }
1749f09cf34dSArchibald Elliott   kstat_close(kc);
1750f09cf34dSArchibald Elliott 
1751f09cf34dSArchibald Elliott   return StringSwitch<const char *>(buf)
1752f09cf34dSArchibald Elliott       .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I
1753f09cf34dSArchibald Elliott       .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I
1754f09cf34dSArchibald Elliott       .Case("TMS390Z55",
1755f09cf34dSArchibald Elliott             "supersparc") // Texas Instruments SuperSPARC I with SuperCache
1756f09cf34dSArchibald Elliott       .Case("MB86904", "supersparc") // Fujitsu microSPARC II
1757f09cf34dSArchibald Elliott       .Case("MB86907", "supersparc") // Fujitsu TurboSPARC
1758f09cf34dSArchibald Elliott       .Case("RT623", "hypersparc")   // Ross hyperSPARC
1759f09cf34dSArchibald Elliott       .Case("RT625", "hypersparc")
1760f09cf34dSArchibald Elliott       .Case("RT626", "hypersparc")
1761f09cf34dSArchibald Elliott       .Case("UltraSPARC-I", "ultrasparc")
1762f09cf34dSArchibald Elliott       .Case("UltraSPARC-II", "ultrasparc")
1763f09cf34dSArchibald Elliott       .Case("UltraSPARC-IIe", "ultrasparc")
1764f09cf34dSArchibald Elliott       .Case("UltraSPARC-IIi", "ultrasparc")
1765f09cf34dSArchibald Elliott       .Case("SPARC64-III", "ultrasparc")
1766f09cf34dSArchibald Elliott       .Case("SPARC64-IV", "ultrasparc")
1767f09cf34dSArchibald Elliott       .Case("UltraSPARC-III", "ultrasparc3")
1768f09cf34dSArchibald Elliott       .Case("UltraSPARC-III+", "ultrasparc3")
1769f09cf34dSArchibald Elliott       .Case("UltraSPARC-IIIi", "ultrasparc3")
1770f09cf34dSArchibald Elliott       .Case("UltraSPARC-IIIi+", "ultrasparc3")
1771f09cf34dSArchibald Elliott       .Case("UltraSPARC-IV", "ultrasparc3")
1772f09cf34dSArchibald Elliott       .Case("UltraSPARC-IV+", "ultrasparc3")
1773f09cf34dSArchibald Elliott       .Case("SPARC64-V", "ultrasparc3")
1774f09cf34dSArchibald Elliott       .Case("SPARC64-VI", "ultrasparc3")
1775f09cf34dSArchibald Elliott       .Case("SPARC64-VII", "ultrasparc3")
1776f09cf34dSArchibald Elliott       .Case("UltraSPARC-T1", "niagara")
1777f09cf34dSArchibald Elliott       .Case("UltraSPARC-T2", "niagara2")
1778f09cf34dSArchibald Elliott       .Case("UltraSPARC-T2", "niagara2")
1779f09cf34dSArchibald Elliott       .Case("UltraSPARC-T2+", "niagara2")
1780f09cf34dSArchibald Elliott       .Case("SPARC-T3", "niagara3")
1781f09cf34dSArchibald Elliott       .Case("SPARC-T4", "niagara4")
1782f09cf34dSArchibald Elliott       .Case("SPARC-T5", "niagara4")
1783f09cf34dSArchibald Elliott       // niagara7/m8 not supported by LLVM yet.
1784f09cf34dSArchibald Elliott       .Case("SPARC-M7", "niagara4" /* "niagara7" */)
1785f09cf34dSArchibald Elliott       .Case("SPARC-S7", "niagara4" /* "niagara7" */)
1786f09cf34dSArchibald Elliott       .Case("SPARC-M8", "niagara4" /* "m8" */)
1787f09cf34dSArchibald Elliott       .Default("generic");
1788f09cf34dSArchibald Elliott #else
1789f09cf34dSArchibald Elliott   return "generic";
1790f09cf34dSArchibald Elliott #endif
1791f09cf34dSArchibald Elliott }
1792f09cf34dSArchibald Elliott #else
1793f09cf34dSArchibald Elliott StringRef sys::getHostCPUName() { return "generic"; }
1794f09cf34dSArchibald Elliott namespace llvm {
1795f09cf34dSArchibald Elliott namespace sys {
1796f09cf34dSArchibald Elliott namespace detail {
1797f09cf34dSArchibald Elliott namespace x86 {
1798f09cf34dSArchibald Elliott 
1799f09cf34dSArchibald Elliott VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
1800f09cf34dSArchibald Elliott   return VendorSignatures::UNKNOWN;
1801f09cf34dSArchibald Elliott }
1802f09cf34dSArchibald Elliott 
1803f09cf34dSArchibald Elliott } // namespace x86
1804f09cf34dSArchibald Elliott } // namespace detail
1805f09cf34dSArchibald Elliott } // namespace sys
1806f09cf34dSArchibald Elliott } // namespace llvm
1807f09cf34dSArchibald Elliott #endif
1808f09cf34dSArchibald Elliott 
1809f09cf34dSArchibald Elliott #if defined(__i386__) || defined(_M_IX86) || \
1810f09cf34dSArchibald Elliott     defined(__x86_64__) || defined(_M_X64)
181118e70a4dSDavid Spickett const StringMap<bool> sys::getHostCPUFeatures() {
1812f09cf34dSArchibald Elliott   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1813f09cf34dSArchibald Elliott   unsigned MaxLevel;
181418e70a4dSDavid Spickett   StringMap<bool> Features;
1815f09cf34dSArchibald Elliott 
1816f09cf34dSArchibald Elliott   if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)
181718e70a4dSDavid Spickett     return Features;
1818f09cf34dSArchibald Elliott 
1819f09cf34dSArchibald Elliott   getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
1820f09cf34dSArchibald Elliott 
1821f09cf34dSArchibald Elliott   Features["cx8"]    = (EDX >>  8) & 1;
1822f09cf34dSArchibald Elliott   Features["cmov"]   = (EDX >> 15) & 1;
1823f09cf34dSArchibald Elliott   Features["mmx"]    = (EDX >> 23) & 1;
1824f09cf34dSArchibald Elliott   Features["fxsr"]   = (EDX >> 24) & 1;
1825f09cf34dSArchibald Elliott   Features["sse"]    = (EDX >> 25) & 1;
1826f09cf34dSArchibald Elliott   Features["sse2"]   = (EDX >> 26) & 1;
1827f09cf34dSArchibald Elliott 
1828f09cf34dSArchibald Elliott   Features["sse3"]   = (ECX >>  0) & 1;
1829f09cf34dSArchibald Elliott   Features["pclmul"] = (ECX >>  1) & 1;
1830f09cf34dSArchibald Elliott   Features["ssse3"]  = (ECX >>  9) & 1;
1831f09cf34dSArchibald Elliott   Features["cx16"]   = (ECX >> 13) & 1;
1832f09cf34dSArchibald Elliott   Features["sse4.1"] = (ECX >> 19) & 1;
1833f09cf34dSArchibald Elliott   Features["sse4.2"] = (ECX >> 20) & 1;
1834f09cf34dSArchibald Elliott   Features["crc32"]  = Features["sse4.2"];
1835f09cf34dSArchibald Elliott   Features["movbe"]  = (ECX >> 22) & 1;
1836f09cf34dSArchibald Elliott   Features["popcnt"] = (ECX >> 23) & 1;
1837f09cf34dSArchibald Elliott   Features["aes"]    = (ECX >> 25) & 1;
1838f09cf34dSArchibald Elliott   Features["rdrnd"]  = (ECX >> 30) & 1;
1839f09cf34dSArchibald Elliott 
1840f09cf34dSArchibald Elliott   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
1841f09cf34dSArchibald Elliott   // indicates that the AVX registers will be saved and restored on context
1842f09cf34dSArchibald Elliott   // switch, then we have full AVX support.
1843f09cf34dSArchibald Elliott   bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
1844f09cf34dSArchibald Elliott   bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);
1845f09cf34dSArchibald Elliott #if defined(__APPLE__)
1846f09cf34dSArchibald Elliott   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1847f09cf34dSArchibald Elliott   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1848f09cf34dSArchibald Elliott   // set right now.
1849f09cf34dSArchibald Elliott   bool HasAVX512Save = true;
1850f09cf34dSArchibald Elliott #else
1851f09cf34dSArchibald Elliott   // AVX512 requires additional context to be saved by the OS.
1852f09cf34dSArchibald Elliott   bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1853f09cf34dSArchibald Elliott #endif
1854f09cf34dSArchibald Elliott   // AMX requires additional context to be saved by the OS.
1855f09cf34dSArchibald Elliott   const unsigned AMXBits = (1 << 17) | (1 << 18);
1856f09cf34dSArchibald Elliott   bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
1857f09cf34dSArchibald Elliott 
1858f09cf34dSArchibald Elliott   Features["avx"]   = HasAVXSave;
1859f09cf34dSArchibald Elliott   Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;
1860f09cf34dSArchibald Elliott   // Only enable XSAVE if OS has enabled support for saving YMM state.
1861f09cf34dSArchibald Elliott   Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1862f09cf34dSArchibald Elliott   Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;
1863f09cf34dSArchibald Elliott 
1864f09cf34dSArchibald Elliott   unsigned MaxExtLevel;
1865f09cf34dSArchibald Elliott   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1866f09cf34dSArchibald Elliott 
1867f09cf34dSArchibald Elliott   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1868f09cf34dSArchibald Elliott                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1869f09cf34dSArchibald Elliott   Features["sahf"]   = HasExtLeaf1 && ((ECX >>  0) & 1);
1870f09cf34dSArchibald Elliott   Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);
1871f09cf34dSArchibald Elliott   Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);
1872f09cf34dSArchibald Elliott   Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);
1873f09cf34dSArchibald Elliott   Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1874f09cf34dSArchibald Elliott   Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);
1875f09cf34dSArchibald Elliott   Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
1876f09cf34dSArchibald Elliott   Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);
1877f09cf34dSArchibald Elliott   Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
1878f09cf34dSArchibald Elliott 
1879f09cf34dSArchibald Elliott   Features["64bit"]  = HasExtLeaf1 && ((EDX >> 29) & 1);
1880f09cf34dSArchibald Elliott 
1881f09cf34dSArchibald Elliott   // Miscellaneous memory related features, detected by
1882f09cf34dSArchibald Elliott   // using the 0x80000008 leaf of the CPUID instruction
1883f09cf34dSArchibald Elliott   bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
1884f09cf34dSArchibald Elliott                      !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
1885f09cf34dSArchibald Elliott   Features["clzero"]   = HasExtLeaf8 && ((EBX >> 0) & 1);
1886f09cf34dSArchibald Elliott   Features["rdpru"]    = HasExtLeaf8 && ((EBX >> 4) & 1);
1887f09cf34dSArchibald Elliott   Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
1888f09cf34dSArchibald Elliott 
1889f09cf34dSArchibald Elliott   bool HasLeaf7 =
1890f09cf34dSArchibald Elliott       MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
1891f09cf34dSArchibald Elliott 
1892f09cf34dSArchibald Elliott   Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);
1893f09cf34dSArchibald Elliott   Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);
1894f09cf34dSArchibald Elliott   Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);
1895f09cf34dSArchibald Elliott   // AVX2 is only supported if we have the OS save support from AVX.
1896f09cf34dSArchibald Elliott   Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;
1897f09cf34dSArchibald Elliott   Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);
1898f09cf34dSArchibald Elliott   Features["invpcid"]    = HasLeaf7 && ((EBX >> 10) & 1);
1899f09cf34dSArchibald Elliott   Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);
1900f09cf34dSArchibald Elliott   // AVX512 is only supported if the OS supports the context save for it.
1901f09cf34dSArchibald Elliott   Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
190287f34078SPhoebe Wang   if (Features["avx512f"])
190387f34078SPhoebe Wang     Features["evex512"]  = true;
1904f09cf34dSArchibald Elliott   Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1905f09cf34dSArchibald Elliott   Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);
1906f09cf34dSArchibald Elliott   Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);
1907f09cf34dSArchibald Elliott   Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
1908f09cf34dSArchibald Elliott   Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1909f09cf34dSArchibald Elliott   Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);
1910f09cf34dSArchibald Elliott   Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1911f09cf34dSArchibald Elliott   Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);
1912f09cf34dSArchibald Elliott   Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
1913f09cf34dSArchibald Elliott   Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
1914f09cf34dSArchibald Elliott 
1915f09cf34dSArchibald Elliott   Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;
1916f09cf34dSArchibald Elliott   Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);
1917f09cf34dSArchibald Elliott   Features["waitpkg"]         = HasLeaf7 && ((ECX >>  5) & 1);
1918f09cf34dSArchibald Elliott   Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;
1919f09cf34dSArchibald Elliott   Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);
1920f09cf34dSArchibald Elliott   Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);
1921f09cf34dSArchibald Elliott   Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;
1922f09cf34dSArchibald Elliott   Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1923f09cf34dSArchibald Elliott   Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1924f09cf34dSArchibald Elliott   Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
1925f09cf34dSArchibald Elliott   Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
1926f09cf34dSArchibald Elliott   Features["rdpid"]           = HasLeaf7 && ((ECX >> 22) & 1);
1927f09cf34dSArchibald Elliott   Features["kl"]              = HasLeaf7 && ((ECX >> 23) & 1); // key locker
1928f09cf34dSArchibald Elliott   Features["cldemote"]        = HasLeaf7 && ((ECX >> 25) & 1);
1929f09cf34dSArchibald Elliott   Features["movdiri"]         = HasLeaf7 && ((ECX >> 27) & 1);
1930f09cf34dSArchibald Elliott   Features["movdir64b"]       = HasLeaf7 && ((ECX >> 28) & 1);
1931f09cf34dSArchibald Elliott   Features["enqcmd"]          = HasLeaf7 && ((ECX >> 29) & 1);
1932f09cf34dSArchibald Elliott 
1933f09cf34dSArchibald Elliott   Features["uintr"]           = HasLeaf7 && ((EDX >> 5) & 1);
1934f09cf34dSArchibald Elliott   Features["avx512vp2intersect"] =
1935f09cf34dSArchibald Elliott       HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;
1936f09cf34dSArchibald Elliott   Features["serialize"]       = HasLeaf7 && ((EDX >> 14) & 1);
1937f09cf34dSArchibald Elliott   Features["tsxldtrk"]        = HasLeaf7 && ((EDX >> 16) & 1);
1938f09cf34dSArchibald Elliott   // There are two CPUID leafs which information associated with the pconfig
1939f09cf34dSArchibald Elliott   // instruction:
1940f09cf34dSArchibald Elliott   // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
1941f09cf34dSArchibald Elliott   // bit of EDX), while the EAX=0x1b leaf returns information on the
1942f09cf34dSArchibald Elliott   // availability of specific pconfig leafs.
1943f09cf34dSArchibald Elliott   // The target feature here only refers to the the first of these two.
1944f09cf34dSArchibald Elliott   // Users might need to check for the availability of specific pconfig
1945f09cf34dSArchibald Elliott   // leaves using cpuid, since that information is ignored while
1946f09cf34dSArchibald Elliott   // detecting features using the "-march=native" flag.
1947f09cf34dSArchibald Elliott   // For more info, see X86 ISA docs.
1948f09cf34dSArchibald Elliott   Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
1949f09cf34dSArchibald Elliott   Features["amx-bf16"]   = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;
1950f09cf34dSArchibald Elliott   Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;
1951f09cf34dSArchibald Elliott   Features["amx-tile"]   = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;
1952f09cf34dSArchibald Elliott   Features["amx-int8"]   = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;
19532a5e3f4cSCraig Topper   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
19542a5e3f4cSCraig Topper   // return all 0s for invalid subleaves so check the limit.
1955f09cf34dSArchibald Elliott   bool HasLeaf7Subleaf1 =
19562a5e3f4cSCraig Topper       HasLeaf7 && EAX >= 1 &&
19572a5e3f4cSCraig Topper       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
1958fc3b7874SFreddy Ye   Features["sha512"]     = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);
1959c6f66de2SFreddy Ye   Features["sm3"]        = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);
1960049d6a3fSFreddy Ye   Features["sm4"]        = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);
1961f09cf34dSArchibald Elliott   Features["raoint"]     = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);
1962f09cf34dSArchibald Elliott   Features["avxvnni"]    = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;
1963f09cf34dSArchibald Elliott   Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;
1964f09cf34dSArchibald Elliott   Features["amx-fp16"]   = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;
1965f09cf34dSArchibald Elliott   Features["cmpccxadd"]  = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);
1966f09cf34dSArchibald Elliott   Features["hreset"]     = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);
1967f09cf34dSArchibald Elliott   Features["avxifma"]    = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;
1968c4248fa3SFreddy Ye   Features["movrs"] = HasLeaf7Subleaf1 && ((EAX >> 31) & 1);
1969f09cf34dSArchibald Elliott   Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;
1970f09cf34dSArchibald Elliott   Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;
197171249fd7SFreddy Ye   Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;
19721c154bd7SFreddy Ye   Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;
1973f09cf34dSArchibald Elliott   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
1974819ac45dSFreddy Ye   Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);
1975259ca9eeSPhoebe Wang   bool HasAVX10 = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
19761fe6be87SFreddy Ye   bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);
19771fe6be87SFreddy Ye   Features["egpr"] = HasAPXF;
19781fe6be87SFreddy Ye   Features["push2pop2"] = HasAPXF;
19791fe6be87SFreddy Ye   Features["ppx"] = HasAPXF;
19801fe6be87SFreddy Ye   Features["ndd"] = HasAPXF;
19811fe6be87SFreddy Ye   Features["ccmp"] = HasAPXF;
198295e9afffSShengchen Kan   Features["nf"] = HasAPXF;
19831fe6be87SFreddy Ye   Features["cf"] = HasAPXF;
198495e9afffSShengchen Kan   Features["zu"] = HasAPXF;
1985f09cf34dSArchibald Elliott 
1986f09cf34dSArchibald Elliott   bool HasLeafD = MaxLevel >= 0xd &&
1987f09cf34dSArchibald Elliott                   !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1988f09cf34dSArchibald Elliott 
1989f09cf34dSArchibald Elliott   // Only enable XSAVE if OS has enabled support for saving YMM state.
1990f09cf34dSArchibald Elliott   Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1991f09cf34dSArchibald Elliott   Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1992f09cf34dSArchibald Elliott   Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
1993f09cf34dSArchibald Elliott 
1994f09cf34dSArchibald Elliott   bool HasLeaf14 = MaxLevel >= 0x14 &&
1995f09cf34dSArchibald Elliott                   !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
1996f09cf34dSArchibald Elliott 
1997f09cf34dSArchibald Elliott   Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
1998f09cf34dSArchibald Elliott 
1999f09cf34dSArchibald Elliott   bool HasLeaf19 =
2000f09cf34dSArchibald Elliott       MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);
2001f09cf34dSArchibald Elliott   Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);
2002f09cf34dSArchibald Elliott 
200381271624SFeng Zou   bool HasLeaf1E = MaxLevel >= 0x1e &&
200481271624SFeng Zou                    !getX86CpuIDAndInfoEx(0x1e, 0x1, &EAX, &EBX, &ECX, &EDX);
200581271624SFeng Zou   Features["amx-fp8"] = HasLeaf1E && ((EAX >> 4) & 1) && HasAMXSave;
2006c72a751dSPhoebe Wang   Features["amx-transpose"] = HasLeaf1E && ((EAX >> 5) & 1) && HasAMXSave;
2007eddb79d5SFeng Zou   Features["amx-tf32"] = HasLeaf1E && ((EAX >> 6) & 1) && HasAMXSave;
20088f440137SPhoebe Wang   Features["amx-avx512"] = HasLeaf1E && ((EAX >> 7) & 1) && HasAMXSave;
2009f77101eaSMalay Sanghi   Features["amx-movrs"] = HasLeaf1E && ((EAX >> 8) & 1) && HasAMXSave;
201081271624SFeng Zou 
2011cfbf0a50SPhoebe Wang   bool HasLeaf24 =
2012cfbf0a50SPhoebe Wang       MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);
2013259ca9eeSPhoebe Wang 
2014259ca9eeSPhoebe Wang   int AVX10Ver = HasLeaf24 && (EBX & 0xff);
2015259ca9eeSPhoebe Wang   int Has512Len = HasLeaf24 && ((EBX >> 18) & 1);
2016259ca9eeSPhoebe Wang   Features["avx10.1-256"] = HasAVX10 && AVX10Ver >= 1;
2017259ca9eeSPhoebe Wang   Features["avx10.1-512"] = HasAVX10 && AVX10Ver >= 1 && Has512Len;
2018259ca9eeSPhoebe Wang   Features["avx10.2-256"] = HasAVX10 && AVX10Ver >= 2;
2019259ca9eeSPhoebe Wang   Features["avx10.2-512"] = HasAVX10 && AVX10Ver >= 2 && Has512Len;
2020cfbf0a50SPhoebe Wang 
202118e70a4dSDavid Spickett   return Features;
2022f09cf34dSArchibald Elliott }
2023f09cf34dSArchibald Elliott #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
202418e70a4dSDavid Spickett const StringMap<bool> sys::getHostCPUFeatures() {
202518e70a4dSDavid Spickett   StringMap<bool> Features;
2026f09cf34dSArchibald Elliott   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
2027f09cf34dSArchibald Elliott   if (!P)
202818e70a4dSDavid Spickett     return Features;
2029f09cf34dSArchibald Elliott 
2030f09cf34dSArchibald Elliott   SmallVector<StringRef, 32> Lines;
2031fd38a955SCraig Topper   P->getBuffer().split(Lines, '\n');
2032f09cf34dSArchibald Elliott 
2033f09cf34dSArchibald Elliott   SmallVector<StringRef, 32> CPUFeatures;
2034f09cf34dSArchibald Elliott 
2035f09cf34dSArchibald Elliott   // Look for the CPU features.
2036f09cf34dSArchibald Elliott   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
2037038871aeSKazu Hirata     if (Lines[I].starts_with("Features")) {
2038f09cf34dSArchibald Elliott       Lines[I].split(CPUFeatures, ' ');
2039f09cf34dSArchibald Elliott       break;
2040f09cf34dSArchibald Elliott     }
2041f09cf34dSArchibald Elliott 
2042f09cf34dSArchibald Elliott #if defined(__aarch64__)
2043b8028f6bSJubilee   // All of these are "crypto" features, but we must sift out actual features
2044b8028f6bSJubilee   // as the former meaning of "crypto" as a single feature is no more.
2045f09cf34dSArchibald Elliott   enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
2046f09cf34dSArchibald Elliott   uint32_t crypto = 0;
2047f09cf34dSArchibald Elliott #endif
2048f09cf34dSArchibald Elliott 
2049f09cf34dSArchibald Elliott   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
2050f09cf34dSArchibald Elliott     StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
2051f09cf34dSArchibald Elliott #if defined(__aarch64__)
2052f09cf34dSArchibald Elliott                                    .Case("asimd", "neon")
2053f09cf34dSArchibald Elliott                                    .Case("fp", "fp-armv8")
2054f09cf34dSArchibald Elliott                                    .Case("crc32", "crc")
2055f09cf34dSArchibald Elliott                                    .Case("atomics", "lse")
2056f09cf34dSArchibald Elliott                                    .Case("sve", "sve")
2057f09cf34dSArchibald Elliott                                    .Case("sve2", "sve2")
2058f09cf34dSArchibald Elliott #else
2059f09cf34dSArchibald Elliott                                    .Case("half", "fp16")
2060f09cf34dSArchibald Elliott                                    .Case("neon", "neon")
2061f09cf34dSArchibald Elliott                                    .Case("vfpv3", "vfp3")
2062f09cf34dSArchibald Elliott                                    .Case("vfpv3d16", "vfp3d16")
2063f09cf34dSArchibald Elliott                                    .Case("vfpv4", "vfp4")
2064f09cf34dSArchibald Elliott                                    .Case("idiva", "hwdiv-arm")
2065f09cf34dSArchibald Elliott                                    .Case("idivt", "hwdiv")
2066f09cf34dSArchibald Elliott #endif
2067f09cf34dSArchibald Elliott                                    .Default("");
2068f09cf34dSArchibald Elliott 
2069f09cf34dSArchibald Elliott #if defined(__aarch64__)
2070f09cf34dSArchibald Elliott     // We need to check crypto separately since we need all of the crypto
2071f09cf34dSArchibald Elliott     // extensions to enable the subtarget feature
2072f09cf34dSArchibald Elliott     if (CPUFeatures[I] == "aes")
2073f09cf34dSArchibald Elliott       crypto |= CAP_AES;
2074f09cf34dSArchibald Elliott     else if (CPUFeatures[I] == "pmull")
2075f09cf34dSArchibald Elliott       crypto |= CAP_PMULL;
2076f09cf34dSArchibald Elliott     else if (CPUFeatures[I] == "sha1")
2077f09cf34dSArchibald Elliott       crypto |= CAP_SHA1;
2078f09cf34dSArchibald Elliott     else if (CPUFeatures[I] == "sha2")
2079f09cf34dSArchibald Elliott       crypto |= CAP_SHA2;
2080f09cf34dSArchibald Elliott #endif
2081f09cf34dSArchibald Elliott 
2082f09cf34dSArchibald Elliott     if (LLVMFeatureStr != "")
2083f09cf34dSArchibald Elliott       Features[LLVMFeatureStr] = true;
2084f09cf34dSArchibald Elliott   }
2085f09cf34dSArchibald Elliott 
2086f09cf34dSArchibald Elliott #if defined(__aarch64__)
2087b8028f6bSJubilee   // LLVM has decided some AArch64 CPUs have all the instructions they _may_
2088b8028f6bSJubilee   // have, as opposed to all the instructions they _must_ have, so allow runtime
2089b8028f6bSJubilee   // information to correct us on that.
2090b8028f6bSJubilee   uint32_t Aes = CAP_AES | CAP_PMULL;
2091b8028f6bSJubilee   uint32_t Sha2 = CAP_SHA1 | CAP_SHA2;
2092b8028f6bSJubilee   Features["aes"] = (crypto & Aes) == Aes;
2093b8028f6bSJubilee   Features["sha2"] = (crypto & Sha2) == Sha2;
2094f09cf34dSArchibald Elliott #endif
2095f09cf34dSArchibald Elliott 
209618e70a4dSDavid Spickett   return Features;
2097f09cf34dSArchibald Elliott }
2098f09cf34dSArchibald Elliott #elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
209918e70a4dSDavid Spickett const StringMap<bool> sys::getHostCPUFeatures() {
210018e70a4dSDavid Spickett   StringMap<bool> Features;
210118e70a4dSDavid Spickett 
2102b8028f6bSJubilee   // If we're asking the OS at runtime, believe what the OS says
2103b8028f6bSJubilee   Features["neon"] =
2104b8028f6bSJubilee       IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
2105b8028f6bSJubilee   Features["crc"] =
2106b8028f6bSJubilee       IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
2107b8028f6bSJubilee 
2108b8028f6bSJubilee   // Avoid inferring "crypto" means more than the traditional AES + SHA2
2109b8028f6bSJubilee   bool TradCrypto =
2110b8028f6bSJubilee       IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
2111b8028f6bSJubilee   Features["aes"] = TradCrypto;
2112b8028f6bSJubilee   Features["sha2"] = TradCrypto;
2113f09cf34dSArchibald Elliott 
211418e70a4dSDavid Spickett   return Features;
2115f09cf34dSArchibald Elliott }
2116e53f41c3Swanglei #elif defined(__linux__) && defined(__loongarch__)
2117e53f41c3Swanglei #include <sys/auxv.h>
211818e70a4dSDavid Spickett const StringMap<bool> sys::getHostCPUFeatures() {
2119e53f41c3Swanglei   unsigned long hwcap = getauxval(AT_HWCAP);
2120e53f41c3Swanglei   bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU
2121e70f9e20SWeining Lu   uint32_t cpucfg2 = 0x2, cpucfg3 = 0x3;
2122e53f41c3Swanglei   __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));
21231d460207Stangaac   __asm__("cpucfg %[cpucfg3], %[cpucfg3]\n\t" : [cpucfg3] "+r"(cpucfg3));
2124e53f41c3Swanglei 
212518e70a4dSDavid Spickett   StringMap<bool> Features;
212618e70a4dSDavid Spickett 
2127e53f41c3Swanglei   Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP
2128e53f41c3Swanglei   Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP
2129e53f41c3Swanglei 
2130e53f41c3Swanglei   Features["lsx"] = hwcap & (1UL << 4);  // HWCAP_LOONGARCH_LSX
2131e53f41c3Swanglei   Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX
2132e53f41c3Swanglei   Features["lvz"] = hwcap & (1UL << 9);  // HWCAP_LOONGARCH_LVZ
2133e53f41c3Swanglei 
21342283d504Stangaac   Features["frecipe"] = cpucfg2 & (1U << 25); // CPUCFG.2.FRECIPE
2135f4379db4Stangaac   Features["div32"] = cpucfg2 & (1U << 26);   // CPUCFG.2.DIV32
21362283d504Stangaac   Features["lam-bh"] = cpucfg2 & (1U << 27);  // CPUCFG.2.LAM_BH
2137427be076Stangaac   Features["lamcas"] = cpucfg2 & (1U << 28);  // CPUCFG.2.LAMCAS
2138*19834b46Stangaac   Features["scq"] = cpucfg2 & (1U << 30);     // CPUCFG.2.SCQ
21392283d504Stangaac 
21401d460207Stangaac   Features["ld-seq-sa"] = cpucfg3 & (1U << 23); // CPUCFG.3.LD_SEQ_SA
21411d460207Stangaac 
21422283d504Stangaac   // TODO: Need to complete.
21432283d504Stangaac   // Features["llacq-screl"] = cpucfg2 & (1U << 29); // CPUCFG.2.LLACQ_SCREL
214418e70a4dSDavid Spickett   return Features;
2145e53f41c3Swanglei }
2146578cf724SYingwei Zheng #elif defined(__linux__) && defined(__riscv)
2147578cf724SYingwei Zheng // struct riscv_hwprobe
2148578cf724SYingwei Zheng struct RISCVHwProbe {
2149578cf724SYingwei Zheng   int64_t Key;
2150578cf724SYingwei Zheng   uint64_t Value;
2151578cf724SYingwei Zheng };
2152578cf724SYingwei Zheng const StringMap<bool> sys::getHostCPUFeatures() {
2153578cf724SYingwei Zheng   RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0},
2154bf895c71SYingwei Zheng                        {/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0},
2155bf895c71SYingwei Zheng                        {/*RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF=*/9, 0}};
2156578cf724SYingwei Zheng   int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,
2157578cf724SYingwei Zheng                     /*pair_count=*/std::size(Query), /*cpu_count=*/0,
2158578cf724SYingwei Zheng                     /*cpus=*/0, /*flags=*/0);
2159578cf724SYingwei Zheng   if (Ret != 0)
2160578cf724SYingwei Zheng     return {};
2161578cf724SYingwei Zheng 
2162578cf724SYingwei Zheng   StringMap<bool> Features;
2163578cf724SYingwei Zheng   uint64_t BaseMask = Query[0].Value;
2164578cf724SYingwei Zheng   // Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set.
2165578cf724SYingwei Zheng   if (BaseMask & 1) {
2166578cf724SYingwei Zheng     Features["i"] = true;
2167578cf724SYingwei Zheng     Features["m"] = true;
2168578cf724SYingwei Zheng     Features["a"] = true;
2169578cf724SYingwei Zheng   }
2170578cf724SYingwei Zheng 
2171578cf724SYingwei Zheng   uint64_t ExtMask = Query[1].Value;
2172578cf724SYingwei Zheng   Features["f"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
2173578cf724SYingwei Zheng   Features["d"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
2174578cf724SYingwei Zheng   Features["c"] = ExtMask & (1 << 1);           // RISCV_HWPROBE_IMA_C
2175578cf724SYingwei Zheng   Features["v"] = ExtMask & (1 << 2);           // RISCV_HWPROBE_IMA_V
2176578cf724SYingwei Zheng   Features["zba"] = ExtMask & (1 << 3);         // RISCV_HWPROBE_EXT_ZBA
2177578cf724SYingwei Zheng   Features["zbb"] = ExtMask & (1 << 4);         // RISCV_HWPROBE_EXT_ZBB
2178578cf724SYingwei Zheng   Features["zbs"] = ExtMask & (1 << 5);         // RISCV_HWPROBE_EXT_ZBS
2179578cf724SYingwei Zheng   Features["zicboz"] = ExtMask & (1 << 6);      // RISCV_HWPROBE_EXT_ZICBOZ
2180578cf724SYingwei Zheng   Features["zbc"] = ExtMask & (1 << 7);         // RISCV_HWPROBE_EXT_ZBC
2181578cf724SYingwei Zheng   Features["zbkb"] = ExtMask & (1 << 8);        // RISCV_HWPROBE_EXT_ZBKB
2182578cf724SYingwei Zheng   Features["zbkc"] = ExtMask & (1 << 9);        // RISCV_HWPROBE_EXT_ZBKC
2183578cf724SYingwei Zheng   Features["zbkx"] = ExtMask & (1 << 10);       // RISCV_HWPROBE_EXT_ZBKX
2184578cf724SYingwei Zheng   Features["zknd"] = ExtMask & (1 << 11);       // RISCV_HWPROBE_EXT_ZKND
2185578cf724SYingwei Zheng   Features["zkne"] = ExtMask & (1 << 12);       // RISCV_HWPROBE_EXT_ZKNE
2186578cf724SYingwei Zheng   Features["zknh"] = ExtMask & (1 << 13);       // RISCV_HWPROBE_EXT_ZKNH
2187578cf724SYingwei Zheng   Features["zksed"] = ExtMask & (1 << 14);      // RISCV_HWPROBE_EXT_ZKSED
2188578cf724SYingwei Zheng   Features["zksh"] = ExtMask & (1 << 15);       // RISCV_HWPROBE_EXT_ZKSH
2189578cf724SYingwei Zheng   Features["zkt"] = ExtMask & (1 << 16);        // RISCV_HWPROBE_EXT_ZKT
2190578cf724SYingwei Zheng   Features["zvbb"] = ExtMask & (1 << 17);       // RISCV_HWPROBE_EXT_ZVBB
2191578cf724SYingwei Zheng   Features["zvbc"] = ExtMask & (1 << 18);       // RISCV_HWPROBE_EXT_ZVBC
2192578cf724SYingwei Zheng   Features["zvkb"] = ExtMask & (1 << 19);       // RISCV_HWPROBE_EXT_ZVKB
2193578cf724SYingwei Zheng   Features["zvkg"] = ExtMask & (1 << 20);       // RISCV_HWPROBE_EXT_ZVKG
2194578cf724SYingwei Zheng   Features["zvkned"] = ExtMask & (1 << 21);     // RISCV_HWPROBE_EXT_ZVKNED
2195578cf724SYingwei Zheng   Features["zvknha"] = ExtMask & (1 << 22);     // RISCV_HWPROBE_EXT_ZVKNHA
2196578cf724SYingwei Zheng   Features["zvknhb"] = ExtMask & (1 << 23);     // RISCV_HWPROBE_EXT_ZVKNHB
2197578cf724SYingwei Zheng   Features["zvksed"] = ExtMask & (1 << 24);     // RISCV_HWPROBE_EXT_ZVKSED
2198578cf724SYingwei Zheng   Features["zvksh"] = ExtMask & (1 << 25);      // RISCV_HWPROBE_EXT_ZVKSH
2199578cf724SYingwei Zheng   Features["zvkt"] = ExtMask & (1 << 26);       // RISCV_HWPROBE_EXT_ZVKT
2200578cf724SYingwei Zheng   Features["zfh"] = ExtMask & (1 << 27);        // RISCV_HWPROBE_EXT_ZFH
2201578cf724SYingwei Zheng   Features["zfhmin"] = ExtMask & (1 << 28);     // RISCV_HWPROBE_EXT_ZFHMIN
2202578cf724SYingwei Zheng   Features["zihintntl"] = ExtMask & (1 << 29);  // RISCV_HWPROBE_EXT_ZIHINTNTL
2203578cf724SYingwei Zheng   Features["zvfh"] = ExtMask & (1 << 30);       // RISCV_HWPROBE_EXT_ZVFH
2204578cf724SYingwei Zheng   Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN
2205578cf724SYingwei Zheng   Features["zfa"] = ExtMask & (1ULL << 32);     // RISCV_HWPROBE_EXT_ZFA
2206578cf724SYingwei Zheng   Features["ztso"] = ExtMask & (1ULL << 33);    // RISCV_HWPROBE_EXT_ZTSO
2207614aeda9SAlex Bradbury   Features["zacas"] = ExtMask & (1ULL << 34);   // RISCV_HWPROBE_EXT_ZACAS
2208578cf724SYingwei Zheng   Features["zicond"] = ExtMask & (1ULL << 35);  // RISCV_HWPROBE_EXT_ZICOND
2209578cf724SYingwei Zheng   Features["zihintpause"] =
2210578cf724SYingwei Zheng       ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE
2211bf895c71SYingwei Zheng   Features["zve32x"] = ExtMask & (1ULL << 37); // RISCV_HWPROBE_EXT_ZVE32X
2212bf895c71SYingwei Zheng   Features["zve32f"] = ExtMask & (1ULL << 38); // RISCV_HWPROBE_EXT_ZVE32F
2213bf895c71SYingwei Zheng   Features["zve64x"] = ExtMask & (1ULL << 39); // RISCV_HWPROBE_EXT_ZVE64X
2214bf895c71SYingwei Zheng   Features["zve64f"] = ExtMask & (1ULL << 40); // RISCV_HWPROBE_EXT_ZVE64F
2215bf895c71SYingwei Zheng   Features["zve64d"] = ExtMask & (1ULL << 41); // RISCV_HWPROBE_EXT_ZVE64D
2216bf895c71SYingwei Zheng   Features["zimop"] = ExtMask & (1ULL << 42);  // RISCV_HWPROBE_EXT_ZIMOP
2217bf895c71SYingwei Zheng   Features["zca"] = ExtMask & (1ULL << 43);    // RISCV_HWPROBE_EXT_ZCA
2218bf895c71SYingwei Zheng   Features["zcb"] = ExtMask & (1ULL << 44);    // RISCV_HWPROBE_EXT_ZCB
2219bf895c71SYingwei Zheng   Features["zcd"] = ExtMask & (1ULL << 45);    // RISCV_HWPROBE_EXT_ZCD
2220bf895c71SYingwei Zheng   Features["zcf"] = ExtMask & (1ULL << 46);    // RISCV_HWPROBE_EXT_ZCF
2221bf895c71SYingwei Zheng   Features["zcmop"] = ExtMask & (1ULL << 47);  // RISCV_HWPROBE_EXT_ZCMOP
2222bf895c71SYingwei Zheng   Features["zawrs"] = ExtMask & (1ULL << 48);  // RISCV_HWPROBE_EXT_ZAWRS
2223578cf724SYingwei Zheng 
2224bf895c71SYingwei Zheng   // Check whether the processor supports fast misaligned scalar memory access.
2225bf895c71SYingwei Zheng   // NOTE: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF is only available on
2226bf895c71SYingwei Zheng   // Linux 6.11 or later. If it is not recognized, the key field will be cleared
2227bf895c71SYingwei Zheng   // to -1.
2228bf895c71SYingwei Zheng   if (Query[2].Key != -1 &&
2229bf895c71SYingwei Zheng       Query[2].Value == /*RISCV_HWPROBE_MISALIGNED_SCALAR_FAST=*/3)
2230bf895c71SYingwei Zheng     Features["unaligned-scalar-mem"] = true;
2231578cf724SYingwei Zheng 
2232578cf724SYingwei Zheng   return Features;
2233578cf724SYingwei Zheng }
2234f09cf34dSArchibald Elliott #else
223518e70a4dSDavid Spickett const StringMap<bool> sys::getHostCPUFeatures() { return {}; }
2236f09cf34dSArchibald Elliott #endif
2237f09cf34dSArchibald Elliott 
2238dc078e6eSJon Roelofs #if __APPLE__
2239dc078e6eSJon Roelofs /// \returns the \p triple, but with the Host's arch spliced in.
2240dc078e6eSJon Roelofs static Triple withHostArch(Triple T) {
2241dc078e6eSJon Roelofs #if defined(__arm__)
2242dc078e6eSJon Roelofs   T.setArch(Triple::arm);
2243dc078e6eSJon Roelofs   T.setArchName("arm");
2244dc078e6eSJon Roelofs #elif defined(__arm64e__)
2245dc078e6eSJon Roelofs   T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);
2246dc078e6eSJon Roelofs   T.setArchName("arm64e");
2247dc078e6eSJon Roelofs #elif defined(__aarch64__)
2248dc078e6eSJon Roelofs   T.setArch(Triple::aarch64);
2249dc078e6eSJon Roelofs   T.setArchName("arm64");
2250dc078e6eSJon Roelofs #elif defined(__x86_64h__)
2251dc078e6eSJon Roelofs   T.setArch(Triple::x86_64);
2252dc078e6eSJon Roelofs   T.setArchName("x86_64h");
2253dc078e6eSJon Roelofs #elif defined(__x86_64__)
2254dc078e6eSJon Roelofs   T.setArch(Triple::x86_64);
2255dc078e6eSJon Roelofs   T.setArchName("x86_64");
2256a5e10e24SKirill A. Korinsky #elif defined(__i386__)
2257a5e10e24SKirill A. Korinsky   T.setArch(Triple::x86);
2258a5e10e24SKirill A. Korinsky   T.setArchName("i386");
2259dc078e6eSJon Roelofs #elif defined(__powerpc__)
2260dc078e6eSJon Roelofs   T.setArch(Triple::ppc);
2261dc078e6eSJon Roelofs   T.setArchName("powerpc");
2262dc078e6eSJon Roelofs #else
2263dc078e6eSJon Roelofs #  error "Unimplemented host arch fixup"
2264dc078e6eSJon Roelofs #endif
2265dc078e6eSJon Roelofs   return T;
2266dc078e6eSJon Roelofs }
2267dc078e6eSJon Roelofs #endif
2268dc078e6eSJon Roelofs 
2269f09cf34dSArchibald Elliott std::string sys::getProcessTriple() {
2270f09cf34dSArchibald Elliott   std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
2271f09cf34dSArchibald Elliott   Triple PT(Triple::normalize(TargetTripleString));
2272f09cf34dSArchibald Elliott 
2273dc078e6eSJon Roelofs #if __APPLE__
2274dc078e6eSJon Roelofs   /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of
2275dc078e6eSJon Roelofs   /// the slices. This fixes that up.
2276dc078e6eSJon Roelofs   PT = withHostArch(PT);
2277dc078e6eSJon Roelofs #endif
2278dc078e6eSJon Roelofs 
2279f09cf34dSArchibald Elliott   if (sizeof(void *) == 8 && PT.isArch32Bit())
2280f09cf34dSArchibald Elliott     PT = PT.get64BitArchVariant();
2281f09cf34dSArchibald Elliott   if (sizeof(void *) == 4 && PT.isArch64Bit())
2282f09cf34dSArchibald Elliott     PT = PT.get32BitArchVariant();
2283f09cf34dSArchibald Elliott 
2284f09cf34dSArchibald Elliott   return PT.str();
2285f09cf34dSArchibald Elliott }
2286f09cf34dSArchibald Elliott 
2287f09cf34dSArchibald Elliott void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {
2288f09cf34dSArchibald Elliott #if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
2289f09cf34dSArchibald Elliott   std::string CPU = std::string(sys::getHostCPUName());
2290f09cf34dSArchibald Elliott   if (CPU == "generic")
2291f09cf34dSArchibald Elliott     CPU = "(unknown)";
2292f09cf34dSArchibald Elliott   OS << "  Default target: " << sys::getDefaultTargetTriple() << '\n'
2293f09cf34dSArchibald Elliott      << "  Host CPU: " << CPU << '\n';
2294f09cf34dSArchibald Elliott #endif
2295f09cf34dSArchibald Elliott }
2296