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