xref: /src/contrib/llvm-project/llvm/lib/TargetParser/Host.cpp (revision c80e69b00d976a5a3b3e84527f270fa7e72a8205)
1e3b55780SDimitry Andric //===-- Host.cpp - Implement OS Host Detection ------------------*- C++ -*-===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
9e3b55780SDimitry Andric //  This file implements the operating system Host detection.
10cf099d11SDimitry Andric //
11cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
12cf099d11SDimitry Andric 
13e3b55780SDimitry Andric #include "llvm/TargetParser/Host.h"
1458b69754SDimitry Andric #include "llvm/ADT/SmallVector.h"
15cfca06d7SDimitry Andric #include "llvm/ADT/StringMap.h"
1658b69754SDimitry Andric #include "llvm/ADT/StringRef.h"
1758b69754SDimitry Andric #include "llvm/ADT/StringSwitch.h"
18eb11fae6SDimitry Andric #include "llvm/Config/llvm-config.h"
19b915e9e0SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
2058b69754SDimitry Andric #include "llvm/Support/raw_ostream.h"
21e3b55780SDimitry Andric #include "llvm/TargetParser/Triple.h"
22e3b55780SDimitry Andric #include "llvm/TargetParser/X86TargetParser.h"
23cf099d11SDimitry Andric #include <string.h>
24cf099d11SDimitry Andric 
25cf099d11SDimitry Andric // Include the platform-specific parts of this class.
26cf099d11SDimitry Andric #ifdef LLVM_ON_UNIX
27cf099d11SDimitry Andric #include "Unix/Host.inc"
28cfca06d7SDimitry Andric #include <sched.h>
29cf099d11SDimitry Andric #endif
30eb11fae6SDimitry Andric #ifdef _WIN32
31cf099d11SDimitry Andric #include "Windows/Host.inc"
32cf099d11SDimitry Andric #endif
33cf099d11SDimitry Andric #ifdef _MSC_VER
34cf099d11SDimitry Andric #include <intrin.h>
35cf099d11SDimitry Andric #endif
36145449b1SDimitry Andric #ifdef __MVS__
37145449b1SDimitry Andric #include "llvm/Support/BCD.h"
38145449b1SDimitry Andric #endif
39145449b1SDimitry Andric #if defined(__APPLE__)
4001095a5dSDimitry Andric #include <mach/host_info.h>
4158b69754SDimitry Andric #include <mach/mach.h>
4258b69754SDimitry Andric #include <mach/mach_host.h>
4358b69754SDimitry Andric #include <mach/machine.h>
44145449b1SDimitry Andric #include <sys/param.h>
45145449b1SDimitry Andric #include <sys/sysctl.h>
4658b69754SDimitry Andric #endif
47344a3780SDimitry Andric #ifdef _AIX
48344a3780SDimitry Andric #include <sys/systemcfg.h>
49344a3780SDimitry Andric #endif
50e3b55780SDimitry Andric #if defined(__sun__) && defined(__svr4__)
51e3b55780SDimitry Andric #include <kstat.h>
52e3b55780SDimitry Andric #endif
53cf099d11SDimitry Andric 
545ca98fd9SDimitry Andric #define DEBUG_TYPE "host-detection"
555ca98fd9SDimitry Andric 
56cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
57cf099d11SDimitry Andric //
58cf099d11SDimitry Andric //  Implementations of the CPU detection routines
59cf099d11SDimitry Andric //
60cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
61cf099d11SDimitry Andric 
62cf099d11SDimitry Andric using namespace llvm;
63cf099d11SDimitry Andric 
6471d5a254SDimitry Andric static std::unique_ptr<llvm::MemoryBuffer>
getProcCpuinfoContent()6571d5a254SDimitry Andric     LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
6671d5a254SDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
6771d5a254SDimitry Andric       llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
6871d5a254SDimitry Andric   if (std::error_code EC = Text.getError()) {
6971d5a254SDimitry Andric     llvm::errs() << "Can't read "
7071d5a254SDimitry Andric                  << "/proc/cpuinfo: " << EC.message() << "\n";
7171d5a254SDimitry Andric     return nullptr;
7271d5a254SDimitry Andric   }
7371d5a254SDimitry Andric   return std::move(*Text);
7471d5a254SDimitry Andric }
7567c32a98SDimitry Andric 
getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent)76eb11fae6SDimitry Andric StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
7771d5a254SDimitry Andric   // Access to the Processor Version Register (PVR) on PowerPC is privileged,
7871d5a254SDimitry Andric   // and so we must use an operating-system interface to determine the current
7971d5a254SDimitry Andric   // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
8071d5a254SDimitry Andric   const char *generic = "generic";
8171d5a254SDimitry Andric 
8271d5a254SDimitry Andric   // The cpu line is second (after the 'processor: 0' line), so if this
8371d5a254SDimitry Andric   // buffer is too small then something has changed (or is wrong).
8471d5a254SDimitry Andric   StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
8571d5a254SDimitry Andric   StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
8671d5a254SDimitry Andric 
8771d5a254SDimitry Andric   StringRef::const_iterator CIP = CPUInfoStart;
8871d5a254SDimitry Andric 
896f8fc217SDimitry Andric   StringRef::const_iterator CPUStart = nullptr;
9071d5a254SDimitry Andric   size_t CPULen = 0;
9171d5a254SDimitry Andric 
9271d5a254SDimitry Andric   // We need to find the first line which starts with cpu, spaces, and a colon.
9371d5a254SDimitry Andric   // After the colon, there may be some additional spaces and then the cpu type.
946f8fc217SDimitry Andric   while (CIP < CPUInfoEnd && CPUStart == nullptr) {
9571d5a254SDimitry Andric     if (CIP < CPUInfoEnd && *CIP == '\n')
9671d5a254SDimitry Andric       ++CIP;
9771d5a254SDimitry Andric 
9871d5a254SDimitry Andric     if (CIP < CPUInfoEnd && *CIP == 'c') {
9971d5a254SDimitry Andric       ++CIP;
10071d5a254SDimitry Andric       if (CIP < CPUInfoEnd && *CIP == 'p') {
10171d5a254SDimitry Andric         ++CIP;
10271d5a254SDimitry Andric         if (CIP < CPUInfoEnd && *CIP == 'u') {
10371d5a254SDimitry Andric           ++CIP;
10471d5a254SDimitry Andric           while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
10571d5a254SDimitry Andric             ++CIP;
10671d5a254SDimitry Andric 
10771d5a254SDimitry Andric           if (CIP < CPUInfoEnd && *CIP == ':') {
10871d5a254SDimitry Andric             ++CIP;
10971d5a254SDimitry Andric             while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
11071d5a254SDimitry Andric               ++CIP;
11171d5a254SDimitry Andric 
11271d5a254SDimitry Andric             if (CIP < CPUInfoEnd) {
11371d5a254SDimitry Andric               CPUStart = CIP;
11471d5a254SDimitry Andric               while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
11571d5a254SDimitry Andric                                           *CIP != ',' && *CIP != '\n'))
11671d5a254SDimitry Andric                 ++CIP;
11771d5a254SDimitry Andric               CPULen = CIP - CPUStart;
11867c32a98SDimitry Andric             }
11967c32a98SDimitry Andric           }
12071d5a254SDimitry Andric         }
12171d5a254SDimitry Andric       }
12271d5a254SDimitry Andric     }
12371d5a254SDimitry Andric 
1246f8fc217SDimitry Andric     if (CPUStart == nullptr)
12571d5a254SDimitry Andric       while (CIP < CPUInfoEnd && *CIP != '\n')
12671d5a254SDimitry Andric         ++CIP;
12771d5a254SDimitry Andric   }
12871d5a254SDimitry Andric 
1296f8fc217SDimitry Andric   if (CPUStart == nullptr)
13071d5a254SDimitry Andric     return generic;
13171d5a254SDimitry Andric 
13271d5a254SDimitry Andric   return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
13371d5a254SDimitry Andric       .Case("604e", "604e")
13471d5a254SDimitry Andric       .Case("604", "604")
13571d5a254SDimitry Andric       .Case("7400", "7400")
13671d5a254SDimitry Andric       .Case("7410", "7400")
13771d5a254SDimitry Andric       .Case("7447", "7400")
13871d5a254SDimitry Andric       .Case("7455", "7450")
13971d5a254SDimitry Andric       .Case("G4", "g4")
14071d5a254SDimitry Andric       .Case("POWER4", "970")
14171d5a254SDimitry Andric       .Case("PPC970FX", "970")
14271d5a254SDimitry Andric       .Case("PPC970MP", "970")
14371d5a254SDimitry Andric       .Case("G5", "g5")
14471d5a254SDimitry Andric       .Case("POWER5", "g5")
14571d5a254SDimitry Andric       .Case("A2", "a2")
14671d5a254SDimitry Andric       .Case("POWER6", "pwr6")
14771d5a254SDimitry Andric       .Case("POWER7", "pwr7")
14871d5a254SDimitry Andric       .Case("POWER8", "pwr8")
14971d5a254SDimitry Andric       .Case("POWER8E", "pwr8")
15071d5a254SDimitry Andric       .Case("POWER8NVL", "pwr8")
15171d5a254SDimitry Andric       .Case("POWER9", "pwr9")
152cfca06d7SDimitry Andric       .Case("POWER10", "pwr10")
153c76260f3SDimitry Andric       .Case("POWER11", "pwr11")
154706b4fc4SDimitry Andric       // FIXME: If we get a simulator or machine with the capabilities of
155706b4fc4SDimitry Andric       // mcpu=future, we should revisit this and add the name reported by the
156706b4fc4SDimitry Andric       // simulator/machine.
15771d5a254SDimitry Andric       .Default(generic);
15871d5a254SDimitry Andric }
15971d5a254SDimitry Andric 
getHostCPUNameForARM(StringRef ProcCpuinfoContent)160eb11fae6SDimitry Andric StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
16171d5a254SDimitry Andric   // The cpuid register on arm is not accessible from user space. On Linux,
16271d5a254SDimitry Andric   // it is exposed through the /proc/cpuinfo file.
16371d5a254SDimitry Andric 
16471d5a254SDimitry Andric   // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
16571d5a254SDimitry Andric   // in all cases.
16671d5a254SDimitry Andric   SmallVector<StringRef, 32> Lines;
16771d5a254SDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
16871d5a254SDimitry Andric 
16971d5a254SDimitry Andric   // Look for the CPU implementer line.
17071d5a254SDimitry Andric   StringRef Implementer;
17171d5a254SDimitry Andric   StringRef Hardware;
172b60736ecSDimitry Andric   StringRef Part;
17371d5a254SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
174312c0ed1SDimitry Andric     if (Lines[I].starts_with("CPU implementer"))
17571d5a254SDimitry Andric       Implementer = Lines[I].substr(15).ltrim("\t :");
176312c0ed1SDimitry Andric     if (Lines[I].starts_with("Hardware"))
17771d5a254SDimitry Andric       Hardware = Lines[I].substr(8).ltrim("\t :");
178312c0ed1SDimitry Andric     if (Lines[I].starts_with("CPU part"))
179b60736ecSDimitry Andric       Part = Lines[I].substr(8).ltrim("\t :");
18071d5a254SDimitry Andric   }
18171d5a254SDimitry Andric 
18271d5a254SDimitry Andric   if (Implementer == "0x41") { // ARM Ltd.
18371d5a254SDimitry Andric     // MSM8992/8994 may give cpu part for the core that the kernel is running on,
18471d5a254SDimitry Andric     // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
185312c0ed1SDimitry Andric     if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996"))
18671d5a254SDimitry Andric       return "cortex-a53";
18771d5a254SDimitry Andric 
18871d5a254SDimitry Andric 
18971d5a254SDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
19071d5a254SDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
19171d5a254SDimitry Andric     // contents are specified in the various processor manuals.
192cfca06d7SDimitry Andric     // This corresponds to the Main ID Register in Technical Reference Manuals.
193cfca06d7SDimitry Andric     // and is used in programs like sys-utils
194b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
19571d5a254SDimitry Andric         .Case("0x926", "arm926ej-s")
19671d5a254SDimitry Andric         .Case("0xb02", "mpcore")
19771d5a254SDimitry Andric         .Case("0xb36", "arm1136j-s")
19871d5a254SDimitry Andric         .Case("0xb56", "arm1156t2-s")
19971d5a254SDimitry Andric         .Case("0xb76", "arm1176jz-s")
200ac9a064cSDimitry Andric         .Case("0xc05", "cortex-a5")
201ac9a064cSDimitry Andric         .Case("0xc07", "cortex-a7")
20271d5a254SDimitry Andric         .Case("0xc08", "cortex-a8")
20371d5a254SDimitry Andric         .Case("0xc09", "cortex-a9")
20471d5a254SDimitry Andric         .Case("0xc0f", "cortex-a15")
205ac9a064cSDimitry Andric         .Case("0xc0e", "cortex-a17")
20671d5a254SDimitry Andric         .Case("0xc20", "cortex-m0")
20771d5a254SDimitry Andric         .Case("0xc23", "cortex-m3")
20871d5a254SDimitry Andric         .Case("0xc24", "cortex-m4")
209ac9a064cSDimitry Andric         .Case("0xc27", "cortex-m7")
210ac9a064cSDimitry Andric         .Case("0xd20", "cortex-m23")
211ac9a064cSDimitry Andric         .Case("0xd21", "cortex-m33")
212b1c73532SDimitry Andric         .Case("0xd24", "cortex-m52")
213cfca06d7SDimitry Andric         .Case("0xd22", "cortex-m55")
214ac9a064cSDimitry Andric         .Case("0xd23", "cortex-m85")
215ac9a064cSDimitry Andric         .Case("0xc18", "cortex-r8")
216ac9a064cSDimitry Andric         .Case("0xd13", "cortex-r52")
217ac9a064cSDimitry Andric         .Case("0xd16", "cortex-r52plus")
218ac9a064cSDimitry Andric         .Case("0xd15", "cortex-r82")
219ac9a064cSDimitry Andric         .Case("0xd14", "cortex-r82ae")
220cfca06d7SDimitry Andric         .Case("0xd02", "cortex-a34")
22171d5a254SDimitry Andric         .Case("0xd04", "cortex-a35")
22271d5a254SDimitry Andric         .Case("0xd03", "cortex-a53")
223e3b55780SDimitry Andric         .Case("0xd05", "cortex-a55")
224e3b55780SDimitry Andric         .Case("0xd46", "cortex-a510")
225b1c73532SDimitry Andric         .Case("0xd80", "cortex-a520")
226ac9a064cSDimitry Andric         .Case("0xd88", "cortex-a520ae")
22771d5a254SDimitry Andric         .Case("0xd07", "cortex-a57")
228ac9a064cSDimitry Andric         .Case("0xd06", "cortex-a65")
229ac9a064cSDimitry Andric         .Case("0xd43", "cortex-a65ae")
23071d5a254SDimitry Andric         .Case("0xd08", "cortex-a72")
23171d5a254SDimitry Andric         .Case("0xd09", "cortex-a73")
232e6d15924SDimitry Andric         .Case("0xd0a", "cortex-a75")
233e6d15924SDimitry Andric         .Case("0xd0b", "cortex-a76")
234ac9a064cSDimitry Andric         .Case("0xd0e", "cortex-a76ae")
235cfca06d7SDimitry Andric         .Case("0xd0d", "cortex-a77")
236cfca06d7SDimitry Andric         .Case("0xd41", "cortex-a78")
237ac9a064cSDimitry Andric         .Case("0xd42", "cortex-a78ae")
238ac9a064cSDimitry Andric         .Case("0xd4b", "cortex-a78c")
239e3b55780SDimitry Andric         .Case("0xd47", "cortex-a710")
240e3b55780SDimitry Andric         .Case("0xd4d", "cortex-a715")
241b1c73532SDimitry Andric         .Case("0xd81", "cortex-a720")
242ac9a064cSDimitry Andric         .Case("0xd89", "cortex-a720ae")
243ac9a064cSDimitry Andric         .Case("0xd87", "cortex-a725")
244cfca06d7SDimitry Andric         .Case("0xd44", "cortex-x1")
245ecbca9f5SDimitry Andric         .Case("0xd4c", "cortex-x1c")
246e3b55780SDimitry Andric         .Case("0xd48", "cortex-x2")
247e3b55780SDimitry Andric         .Case("0xd4e", "cortex-x3")
248b1c73532SDimitry Andric         .Case("0xd82", "cortex-x4")
249ac9a064cSDimitry Andric         .Case("0xd85", "cortex-x925")
250ac9a064cSDimitry Andric         .Case("0xd4a", "neoverse-e1")
251cfca06d7SDimitry Andric         .Case("0xd0c", "neoverse-n1")
252b60736ecSDimitry Andric         .Case("0xd49", "neoverse-n2")
253ac9a064cSDimitry Andric         .Case("0xd8e", "neoverse-n3")
2546f8fc217SDimitry Andric         .Case("0xd40", "neoverse-v1")
255e3b55780SDimitry Andric         .Case("0xd4f", "neoverse-v2")
256ac9a064cSDimitry Andric         .Case("0xd84", "neoverse-v3")
257ac9a064cSDimitry Andric         .Case("0xd83", "neoverse-v3ae")
25871d5a254SDimitry Andric         .Default("generic");
25971d5a254SDimitry Andric   }
26071d5a254SDimitry Andric 
261d8e91e46SDimitry Andric   if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
262b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
263d8e91e46SDimitry Andric       .Case("0x516", "thunderx2t99")
264d8e91e46SDimitry Andric       .Case("0x0516", "thunderx2t99")
265d8e91e46SDimitry Andric       .Case("0xaf", "thunderx2t99")
266d8e91e46SDimitry Andric       .Case("0x0af", "thunderx2t99")
267d8e91e46SDimitry Andric       .Case("0xa1", "thunderxt88")
268d8e91e46SDimitry Andric       .Case("0x0a1", "thunderxt88")
269d8e91e46SDimitry Andric       .Default("generic");
270d8e91e46SDimitry Andric   }
271d8e91e46SDimitry Andric 
272cfca06d7SDimitry Andric   if (Implementer == "0x46") { // Fujitsu Ltd.
273b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
274cfca06d7SDimitry Andric       .Case("0x001", "a64fx")
275cfca06d7SDimitry Andric       .Default("generic");
276cfca06d7SDimitry Andric   }
277cfca06d7SDimitry Andric 
278cfca06d7SDimitry Andric   if (Implementer == "0x4e") { // NVIDIA Corporation
279b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
280cfca06d7SDimitry Andric         .Case("0x004", "carmel")
281cfca06d7SDimitry Andric         .Default("generic");
282cfca06d7SDimitry Andric   }
283cfca06d7SDimitry Andric 
284d8e91e46SDimitry Andric   if (Implementer == "0x48") // HiSilicon Technologies, Inc.
285d8e91e46SDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
286d8e91e46SDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
287d8e91e46SDimitry Andric     // contents are specified in the various processor manuals.
288b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
289d8e91e46SDimitry Andric       .Case("0xd01", "tsv110")
290d8e91e46SDimitry Andric       .Default("generic");
291d8e91e46SDimitry Andric 
29271d5a254SDimitry Andric   if (Implementer == "0x51") // Qualcomm Technologies, Inc.
29371d5a254SDimitry Andric     // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
29471d5a254SDimitry Andric     // values correspond to the "Part number" in the CP15/c0 register. The
29571d5a254SDimitry Andric     // contents are specified in the various processor manuals.
296b60736ecSDimitry Andric     return StringSwitch<const char *>(Part)
29771d5a254SDimitry Andric         .Case("0x06f", "krait") // APQ8064
29871d5a254SDimitry Andric         .Case("0x201", "kryo")
29971d5a254SDimitry Andric         .Case("0x205", "kryo")
300044eb2f6SDimitry Andric         .Case("0x211", "kryo")
301b60736ecSDimitry Andric         .Case("0x800", "cortex-a73") // Kryo 2xx Gold
302b60736ecSDimitry Andric         .Case("0x801", "cortex-a73") // Kryo 2xx Silver
303b60736ecSDimitry Andric         .Case("0x802", "cortex-a75") // Kryo 3xx Gold
304b60736ecSDimitry Andric         .Case("0x803", "cortex-a75") // Kryo 3xx Silver
305b60736ecSDimitry Andric         .Case("0x804", "cortex-a76") // Kryo 4xx Gold
306b60736ecSDimitry Andric         .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver
307edad5bcbSDimitry Andric         .Case("0xc00", "falkor")
308044eb2f6SDimitry Andric         .Case("0xc01", "saphira")
309ac9a064cSDimitry Andric         .Case("0x001", "oryon-1")
31071d5a254SDimitry Andric         .Default("generic");
311044eb2f6SDimitry Andric   if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
312044eb2f6SDimitry Andric     // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
313044eb2f6SDimitry Andric     // any predictive pattern across variants and parts.
314044eb2f6SDimitry Andric     unsigned Variant = 0, Part = 0;
315044eb2f6SDimitry Andric 
316044eb2f6SDimitry Andric     // Look for the CPU variant line, whose value is a 1 digit hexadecimal
317044eb2f6SDimitry Andric     // number, corresponding to the Variant bits in the CP15/C0 register.
318044eb2f6SDimitry Andric     for (auto I : Lines)
319044eb2f6SDimitry Andric       if (I.consume_front("CPU variant"))
320044eb2f6SDimitry Andric         I.ltrim("\t :").getAsInteger(0, Variant);
321044eb2f6SDimitry Andric 
322044eb2f6SDimitry Andric     // Look for the CPU part line, whose value is a 3 digit hexadecimal
323044eb2f6SDimitry Andric     // number, corresponding to the PartNum bits in the CP15/C0 register.
324044eb2f6SDimitry Andric     for (auto I : Lines)
325044eb2f6SDimitry Andric       if (I.consume_front("CPU part"))
326044eb2f6SDimitry Andric         I.ltrim("\t :").getAsInteger(0, Part);
327044eb2f6SDimitry Andric 
328044eb2f6SDimitry Andric     unsigned Exynos = (Variant << 12) | Part;
329044eb2f6SDimitry Andric     switch (Exynos) {
330044eb2f6SDimitry Andric     default:
331706b4fc4SDimitry Andric       // Default by falling through to Exynos M3.
332e3b55780SDimitry Andric       [[fallthrough]];
333706b4fc4SDimitry Andric     case 0x1002:
334706b4fc4SDimitry Andric       return "exynos-m3";
335706b4fc4SDimitry Andric     case 0x1003:
336706b4fc4SDimitry Andric       return "exynos-m4";
337044eb2f6SDimitry Andric     }
338044eb2f6SDimitry Andric   }
339044eb2f6SDimitry Andric 
3404df029ccSDimitry Andric   if (Implementer == "0x6d") { // Microsoft Corporation.
3414df029ccSDimitry Andric     // The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2.
3424df029ccSDimitry Andric     return StringSwitch<const char *>(Part)
3434df029ccSDimitry Andric         .Case("0xd49", "neoverse-n2")
3444df029ccSDimitry Andric         .Default("generic");
3454df029ccSDimitry Andric   }
3464df029ccSDimitry Andric 
347145449b1SDimitry Andric   if (Implementer == "0xc0") { // Ampere Computing
348145449b1SDimitry Andric     return StringSwitch<const char *>(Part)
349145449b1SDimitry Andric         .Case("0xac3", "ampere1")
350e3b55780SDimitry Andric         .Case("0xac4", "ampere1a")
351ac9a064cSDimitry Andric         .Case("0xac5", "ampere1b")
352145449b1SDimitry Andric         .Default("generic");
353145449b1SDimitry Andric   }
354145449b1SDimitry Andric 
35571d5a254SDimitry Andric   return "generic";
35671d5a254SDimitry Andric }
35771d5a254SDimitry Andric 
358344a3780SDimitry Andric namespace {
getCPUNameFromS390Model(unsigned int Id,bool HaveVectorSupport)359344a3780SDimitry Andric StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) {
360344a3780SDimitry Andric   switch (Id) {
361344a3780SDimitry Andric     case 2064:  // z900 not supported by LLVM
362344a3780SDimitry Andric     case 2066:
363344a3780SDimitry Andric     case 2084:  // z990 not supported by LLVM
364344a3780SDimitry Andric     case 2086:
365344a3780SDimitry Andric     case 2094:  // z9-109 not supported by LLVM
366344a3780SDimitry Andric     case 2096:
367344a3780SDimitry Andric       return "generic";
368344a3780SDimitry Andric     case 2097:
369344a3780SDimitry Andric     case 2098:
370344a3780SDimitry Andric       return "z10";
371344a3780SDimitry Andric     case 2817:
372344a3780SDimitry Andric     case 2818:
373344a3780SDimitry Andric       return "z196";
374344a3780SDimitry Andric     case 2827:
375344a3780SDimitry Andric     case 2828:
376344a3780SDimitry Andric       return "zEC12";
377344a3780SDimitry Andric     case 2964:
378344a3780SDimitry Andric     case 2965:
379344a3780SDimitry Andric       return HaveVectorSupport? "z13" : "zEC12";
380344a3780SDimitry Andric     case 3906:
381344a3780SDimitry Andric     case 3907:
382344a3780SDimitry Andric       return HaveVectorSupport? "z14" : "zEC12";
383344a3780SDimitry Andric     case 8561:
384344a3780SDimitry Andric     case 8562:
385344a3780SDimitry Andric       return HaveVectorSupport? "z15" : "zEC12";
386344a3780SDimitry Andric     case 3931:
387344a3780SDimitry Andric     case 3932:
388344a3780SDimitry Andric     default:
389145449b1SDimitry Andric       return HaveVectorSupport? "z16" : "zEC12";
390344a3780SDimitry Andric   }
391344a3780SDimitry Andric }
392344a3780SDimitry Andric } // end anonymous namespace
393344a3780SDimitry Andric 
getHostCPUNameForS390x(StringRef ProcCpuinfoContent)394eb11fae6SDimitry Andric StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
39571d5a254SDimitry Andric   // STIDP is a privileged operation, so use /proc/cpuinfo instead.
39671d5a254SDimitry Andric 
39771d5a254SDimitry Andric   // The "processor 0:" line comes after a fair amount of other information,
39871d5a254SDimitry Andric   // including a cache breakdown, but this should be plenty.
39971d5a254SDimitry Andric   SmallVector<StringRef, 32> Lines;
40071d5a254SDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
40171d5a254SDimitry Andric 
40271d5a254SDimitry Andric   // Look for the CPU features.
40371d5a254SDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
40471d5a254SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
405312c0ed1SDimitry Andric     if (Lines[I].starts_with("features")) {
406b60736ecSDimitry Andric       size_t Pos = Lines[I].find(':');
40771d5a254SDimitry Andric       if (Pos != StringRef::npos) {
40871d5a254SDimitry Andric         Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
40971d5a254SDimitry Andric         break;
41071d5a254SDimitry Andric       }
41171d5a254SDimitry Andric     }
41271d5a254SDimitry Andric 
41371d5a254SDimitry Andric   // We need to check for the presence of vector support independently of
41471d5a254SDimitry Andric   // the machine type, since we may only use the vector register set when
41571d5a254SDimitry Andric   // supported by the kernel (and hypervisor).
41671d5a254SDimitry Andric   bool HaveVectorSupport = false;
41771d5a254SDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
41871d5a254SDimitry Andric     if (CPUFeatures[I] == "vx")
41971d5a254SDimitry Andric       HaveVectorSupport = true;
42071d5a254SDimitry Andric   }
42171d5a254SDimitry Andric 
42271d5a254SDimitry Andric   // Now check the processor machine type.
42371d5a254SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
424312c0ed1SDimitry Andric     if (Lines[I].starts_with("processor ")) {
42571d5a254SDimitry Andric       size_t Pos = Lines[I].find("machine = ");
42671d5a254SDimitry Andric       if (Pos != StringRef::npos) {
42771d5a254SDimitry Andric         Pos += sizeof("machine = ") - 1;
42871d5a254SDimitry Andric         unsigned int Id;
429344a3780SDimitry Andric         if (!Lines[I].drop_front(Pos).getAsInteger(10, Id))
430344a3780SDimitry Andric           return getCPUNameFromS390Model(Id, HaveVectorSupport);
43171d5a254SDimitry Andric       }
43271d5a254SDimitry Andric       break;
43371d5a254SDimitry Andric     }
43471d5a254SDimitry Andric   }
43571d5a254SDimitry Andric 
43671d5a254SDimitry Andric   return "generic";
43771d5a254SDimitry Andric }
43867c32a98SDimitry Andric 
getHostCPUNameForRISCV(StringRef ProcCpuinfoContent)439145449b1SDimitry Andric StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) {
440145449b1SDimitry Andric   // There are 24 lines in /proc/cpuinfo
441145449b1SDimitry Andric   SmallVector<StringRef> Lines;
442145449b1SDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
443145449b1SDimitry Andric 
444145449b1SDimitry Andric   // Look for uarch line to determine cpu name
445145449b1SDimitry Andric   StringRef UArch;
446145449b1SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
447312c0ed1SDimitry Andric     if (Lines[I].starts_with("uarch")) {
448145449b1SDimitry Andric       UArch = Lines[I].substr(5).ltrim("\t :");
449145449b1SDimitry Andric       break;
450145449b1SDimitry Andric     }
451145449b1SDimitry Andric   }
452145449b1SDimitry Andric 
453145449b1SDimitry Andric   return StringSwitch<const char *>(UArch)
454145449b1SDimitry Andric       .Case("sifive,u74-mc", "sifive-u74")
455145449b1SDimitry Andric       .Case("sifive,bullet0", "sifive-u74")
456ac9a064cSDimitry Andric       .Default("");
457145449b1SDimitry Andric }
458145449b1SDimitry Andric 
getHostCPUNameForBPF()459044eb2f6SDimitry Andric StringRef sys::detail::getHostCPUNameForBPF() {
460044eb2f6SDimitry Andric #if !defined(__linux__) || !defined(__x86_64__)
461044eb2f6SDimitry Andric   return "generic";
462044eb2f6SDimitry Andric #else
463e6d15924SDimitry Andric   uint8_t v3_insns[40] __attribute__ ((aligned (8))) =
464e6d15924SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
465e6d15924SDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
466e6d15924SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
467e6d15924SDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
468e6d15924SDimitry Andric       /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
469e6d15924SDimitry Andric       0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
470e6d15924SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
471e6d15924SDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
472e6d15924SDimitry Andric       /* BPF_EXIT_INSN() */
473e6d15924SDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
474e6d15924SDimitry Andric 
475e6d15924SDimitry Andric   uint8_t v2_insns[40] __attribute__ ((aligned (8))) =
476044eb2f6SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 0) */
477044eb2f6SDimitry Andric     { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
478044eb2f6SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_2, 1) */
479044eb2f6SDimitry Andric       0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
480044eb2f6SDimitry Andric       /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
481044eb2f6SDimitry Andric       0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
482044eb2f6SDimitry Andric       /* BPF_MOV64_IMM(BPF_REG_0, 1) */
483044eb2f6SDimitry Andric       0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
484044eb2f6SDimitry Andric       /* BPF_EXIT_INSN() */
485044eb2f6SDimitry Andric       0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
486044eb2f6SDimitry Andric 
487044eb2f6SDimitry Andric   struct bpf_prog_load_attr {
488044eb2f6SDimitry Andric     uint32_t prog_type;
489044eb2f6SDimitry Andric     uint32_t insn_cnt;
490044eb2f6SDimitry Andric     uint64_t insns;
491044eb2f6SDimitry Andric     uint64_t license;
492044eb2f6SDimitry Andric     uint32_t log_level;
493044eb2f6SDimitry Andric     uint32_t log_size;
494044eb2f6SDimitry Andric     uint64_t log_buf;
495044eb2f6SDimitry Andric     uint32_t kern_version;
496044eb2f6SDimitry Andric     uint32_t prog_flags;
497044eb2f6SDimitry Andric   } attr = {};
498044eb2f6SDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
499044eb2f6SDimitry Andric   attr.insn_cnt = 5;
500e6d15924SDimitry Andric   attr.insns = (uint64_t)v3_insns;
501044eb2f6SDimitry Andric   attr.license = (uint64_t)"DUMMY";
502044eb2f6SDimitry Andric 
503e6d15924SDimitry Andric   int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr,
504e6d15924SDimitry Andric                    sizeof(attr));
505e6d15924SDimitry Andric   if (fd >= 0) {
506e6d15924SDimitry Andric     close(fd);
507e6d15924SDimitry Andric     return "v3";
508e6d15924SDimitry Andric   }
509e6d15924SDimitry Andric 
510e6d15924SDimitry Andric   /* Clear the whole attr in case its content changed by syscall. */
511e6d15924SDimitry Andric   memset(&attr, 0, sizeof(attr));
512e6d15924SDimitry Andric   attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
513e6d15924SDimitry Andric   attr.insn_cnt = 5;
514e6d15924SDimitry Andric   attr.insns = (uint64_t)v2_insns;
515e6d15924SDimitry Andric   attr.license = (uint64_t)"DUMMY";
516e6d15924SDimitry Andric   fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
517044eb2f6SDimitry Andric   if (fd >= 0) {
518044eb2f6SDimitry Andric     close(fd);
519044eb2f6SDimitry Andric     return "v2";
520044eb2f6SDimitry Andric   }
521044eb2f6SDimitry Andric   return "v1";
522044eb2f6SDimitry Andric #endif
523044eb2f6SDimitry Andric }
524044eb2f6SDimitry Andric 
525b915e9e0SDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
526b915e9e0SDimitry Andric     defined(__x86_64__) || defined(_M_X64)
527cf099d11SDimitry Andric 
528b915e9e0SDimitry Andric // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
529b915e9e0SDimitry Andric // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
530b915e9e0SDimitry Andric // support. Consequently, for i386, the presence of CPUID is checked first
531b915e9e0SDimitry Andric // via the corresponding eflags bit.
532b915e9e0SDimitry Andric // Removal of cpuid.h header motivated by PR30384
533b915e9e0SDimitry Andric // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
534b915e9e0SDimitry Andric // or test-suite, but are used in external projects e.g. libstdcxx
isCpuIdSupported()535b915e9e0SDimitry Andric static bool isCpuIdSupported() {
536b915e9e0SDimitry Andric #if defined(__GNUC__) || defined(__clang__)
537b915e9e0SDimitry Andric #if defined(__i386__)
538b915e9e0SDimitry Andric   int __cpuid_supported;
539b915e9e0SDimitry Andric   __asm__("  pushfl\n"
540b915e9e0SDimitry Andric           "  popl   %%eax\n"
541b915e9e0SDimitry Andric           "  movl   %%eax,%%ecx\n"
542b915e9e0SDimitry Andric           "  xorl   $0x00200000,%%eax\n"
543b915e9e0SDimitry Andric           "  pushl  %%eax\n"
544b915e9e0SDimitry Andric           "  popfl\n"
545b915e9e0SDimitry Andric           "  pushfl\n"
546b915e9e0SDimitry Andric           "  popl   %%eax\n"
547b915e9e0SDimitry Andric           "  movl   $0,%0\n"
548b915e9e0SDimitry Andric           "  cmpl   %%eax,%%ecx\n"
549b915e9e0SDimitry Andric           "  je     1f\n"
550b915e9e0SDimitry Andric           "  movl   $1,%0\n"
551b915e9e0SDimitry Andric           "1:"
552b915e9e0SDimitry Andric           : "=r"(__cpuid_supported)
553b915e9e0SDimitry Andric           :
554b915e9e0SDimitry Andric           : "eax", "ecx");
555b915e9e0SDimitry Andric   if (!__cpuid_supported)
556b915e9e0SDimitry Andric     return false;
557b915e9e0SDimitry Andric #endif
558b915e9e0SDimitry Andric   return true;
559b915e9e0SDimitry Andric #endif
560b915e9e0SDimitry Andric   return true;
561b915e9e0SDimitry Andric }
562b915e9e0SDimitry Andric 
56301095a5dSDimitry Andric /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
56401095a5dSDimitry Andric /// the specified arguments.  If we can't run cpuid on the host, return true.
getX86CpuIDAndInfo(unsigned value,unsigned * rEAX,unsigned * rEBX,unsigned * rECX,unsigned * rEDX)56501095a5dSDimitry Andric static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
566f8af5cf6SDimitry Andric                                unsigned *rECX, unsigned *rEDX) {
567f8af5cf6SDimitry Andric #if defined(__GNUC__) || defined(__clang__)
568b915e9e0SDimitry Andric #if defined(__x86_64__)
569b915e9e0SDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
570b915e9e0SDimitry Andric   // FIXME: should we save this for Clang?
571b915e9e0SDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
572f8af5cf6SDimitry Andric           "cpuid\n\t"
573f8af5cf6SDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
57401095a5dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
575f8af5cf6SDimitry Andric           : "a"(value));
576ca089b24SDimitry Andric   return false;
577b915e9e0SDimitry Andric #elif defined(__i386__)
578b915e9e0SDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
579f8af5cf6SDimitry Andric           "cpuid\n\t"
580f8af5cf6SDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
58101095a5dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
582f8af5cf6SDimitry Andric           : "a"(value));
583ca089b24SDimitry Andric   return false;
584f8af5cf6SDimitry Andric #else
585ca089b24SDimitry Andric   return true;
586f8af5cf6SDimitry Andric #endif
587f8af5cf6SDimitry Andric #elif defined(_MSC_VER)
588f8af5cf6SDimitry Andric   // The MSVC intrinsic is portable across x86 and x64.
589f8af5cf6SDimitry Andric   int registers[4];
590f8af5cf6SDimitry Andric   __cpuid(registers, value);
591f8af5cf6SDimitry Andric   *rEAX = registers[0];
592f8af5cf6SDimitry Andric   *rEBX = registers[1];
593f8af5cf6SDimitry Andric   *rECX = registers[2];
594f8af5cf6SDimitry Andric   *rEDX = registers[3];
595f8af5cf6SDimitry Andric   return false;
596f8af5cf6SDimitry Andric #else
597f8af5cf6SDimitry Andric   return true;
598f8af5cf6SDimitry Andric #endif
599f8af5cf6SDimitry Andric }
600f8af5cf6SDimitry Andric 
601344a3780SDimitry Andric namespace llvm {
602344a3780SDimitry Andric namespace sys {
603344a3780SDimitry Andric namespace detail {
604344a3780SDimitry Andric namespace x86 {
605344a3780SDimitry Andric 
getVendorSignature(unsigned * MaxLeaf)606344a3780SDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
607344a3780SDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
608344a3780SDimitry Andric   if (MaxLeaf == nullptr)
609344a3780SDimitry Andric     MaxLeaf = &EAX;
610344a3780SDimitry Andric   else
611344a3780SDimitry Andric     *MaxLeaf = 0;
612344a3780SDimitry Andric 
613344a3780SDimitry Andric   if (!isCpuIdSupported())
614344a3780SDimitry Andric     return VendorSignatures::UNKNOWN;
615344a3780SDimitry Andric 
616344a3780SDimitry Andric   if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1)
617344a3780SDimitry Andric     return VendorSignatures::UNKNOWN;
618344a3780SDimitry Andric 
619344a3780SDimitry Andric   // "Genu ineI ntel"
620344a3780SDimitry Andric   if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e)
621344a3780SDimitry Andric     return VendorSignatures::GENUINE_INTEL;
622344a3780SDimitry Andric 
623344a3780SDimitry Andric   // "Auth enti cAMD"
624344a3780SDimitry Andric   if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163)
625344a3780SDimitry Andric     return VendorSignatures::AUTHENTIC_AMD;
626344a3780SDimitry Andric 
627344a3780SDimitry Andric   return VendorSignatures::UNKNOWN;
628344a3780SDimitry Andric }
629344a3780SDimitry Andric 
630344a3780SDimitry Andric } // namespace x86
631344a3780SDimitry Andric } // namespace detail
632344a3780SDimitry Andric } // namespace sys
633344a3780SDimitry Andric } // namespace llvm
634344a3780SDimitry Andric 
635344a3780SDimitry Andric using namespace llvm::sys::detail::x86;
636344a3780SDimitry Andric 
63701095a5dSDimitry Andric /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
63801095a5dSDimitry Andric /// the 4 values in the specified arguments.  If we can't run cpuid on the host,
639f8af5cf6SDimitry Andric /// return true.
getX86CpuIDAndInfoEx(unsigned value,unsigned subleaf,unsigned * rEAX,unsigned * rEBX,unsigned * rECX,unsigned * rEDX)64001095a5dSDimitry Andric static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
6415ca98fd9SDimitry Andric                                  unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
6425ca98fd9SDimitry Andric                                  unsigned *rEDX) {
643b915e9e0SDimitry Andric #if defined(__GNUC__) || defined(__clang__)
64493c91e39SDimitry Andric #if defined(__x86_64__)
645ca089b24SDimitry Andric   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
646b915e9e0SDimitry Andric   // FIXME: should we save this for Clang?
647b915e9e0SDimitry Andric   __asm__("movq\t%%rbx, %%rsi\n\t"
648cf099d11SDimitry Andric           "cpuid\n\t"
649cf099d11SDimitry Andric           "xchgq\t%%rbx, %%rsi\n\t"
65001095a5dSDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
65101095a5dSDimitry Andric           : "a"(value), "c"(subleaf));
652ca089b24SDimitry Andric   return false;
65393c91e39SDimitry Andric #elif defined(__i386__)
65493c91e39SDimitry Andric   __asm__("movl\t%%ebx, %%esi\n\t"
65593c91e39SDimitry Andric           "cpuid\n\t"
65693c91e39SDimitry Andric           "xchgl\t%%ebx, %%esi\n\t"
65793c91e39SDimitry Andric           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
65893c91e39SDimitry Andric           : "a"(value), "c"(subleaf));
65993c91e39SDimitry Andric   return false;
66093c91e39SDimitry Andric #else
66193c91e39SDimitry Andric   return true;
66293c91e39SDimitry Andric #endif
663cf099d11SDimitry Andric #elif defined(_MSC_VER)
664cf099d11SDimitry Andric   int registers[4];
665f8af5cf6SDimitry Andric   __cpuidex(registers, value, subleaf);
666cf099d11SDimitry Andric   *rEAX = registers[0];
667cf099d11SDimitry Andric   *rEBX = registers[1];
668cf099d11SDimitry Andric   *rECX = registers[2];
669cf099d11SDimitry Andric   *rEDX = registers[3];
670ca089b24SDimitry Andric   return false;
671ca089b24SDimitry Andric #else
672ca089b24SDimitry Andric   return true;
673cf099d11SDimitry Andric #endif
674cf099d11SDimitry Andric }
675cf099d11SDimitry Andric 
676ca089b24SDimitry Andric // Read control register 0 (XCR0). Used to detect features such as AVX.
getX86XCR0(unsigned * rEAX,unsigned * rEDX)67701095a5dSDimitry Andric static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
678b915e9e0SDimitry Andric #if defined(__GNUC__) || defined(__clang__)
6794a16efa3SDimitry Andric   // Check xgetbv; this uses a .byte sequence instead of the instruction
6804a16efa3SDimitry Andric   // directly because older assemblers do not include support for xgetbv and
6814a16efa3SDimitry Andric   // there is no easy way to conditionally compile based on the assembler used.
6825a5ac124SDimitry Andric   __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
6835a5ac124SDimitry Andric   return false;
68459d6cff9SDimitry Andric #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
6855a5ac124SDimitry Andric   unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
6865a5ac124SDimitry Andric   *rEAX = Result;
6875a5ac124SDimitry Andric   *rEDX = Result >> 32;
6885a5ac124SDimitry Andric   return false;
6894a16efa3SDimitry Andric #else
6905a5ac124SDimitry Andric   return true;
6914a16efa3SDimitry Andric #endif
6924a16efa3SDimitry Andric }
6934a16efa3SDimitry Andric 
detectX86FamilyModel(unsigned EAX,unsigned * Family,unsigned * Model)69401095a5dSDimitry Andric static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
69501095a5dSDimitry Andric                                  unsigned *Model) {
69601095a5dSDimitry Andric   *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
69701095a5dSDimitry Andric   *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
69801095a5dSDimitry Andric   if (*Family == 6 || *Family == 0xf) {
69901095a5dSDimitry Andric     if (*Family == 0xf)
700cf099d11SDimitry Andric       // Examine extended family ID if family ID is F.
70101095a5dSDimitry Andric       *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
702cf099d11SDimitry Andric     // Examine extended model ID if family ID is 6 or F.
70301095a5dSDimitry Andric     *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
704cf099d11SDimitry Andric   }
705cf099d11SDimitry Andric }
706cf099d11SDimitry Andric 
707ac9a064cSDimitry Andric #define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
708cfca06d7SDimitry Andric 
getIntelProcessorTypeAndSubtype(unsigned Family,unsigned Model,const unsigned * Features,unsigned * Type,unsigned * Subtype)709ac9a064cSDimitry Andric static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,
710ac9a064cSDimitry Andric                                                  unsigned Model,
711ac9a064cSDimitry Andric                                                  const unsigned *Features,
712ac9a064cSDimitry Andric                                                  unsigned *Type,
713ac9a064cSDimitry Andric                                                  unsigned *Subtype) {
714cfca06d7SDimitry Andric   StringRef CPU;
715cfca06d7SDimitry Andric 
716cf099d11SDimitry Andric   switch (Family) {
717cf099d11SDimitry Andric   case 3:
718cfca06d7SDimitry Andric     CPU = "i386";
71901095a5dSDimitry Andric     break;
720cf099d11SDimitry Andric   case 4:
721cfca06d7SDimitry Andric     CPU = "i486";
72201095a5dSDimitry Andric     break;
723cf099d11SDimitry Andric   case 5:
724cfca06d7SDimitry Andric     if (testFeature(X86::FEATURE_MMX)) {
725cfca06d7SDimitry Andric       CPU = "pentium-mmx";
72601095a5dSDimitry Andric       break;
727cf099d11SDimitry Andric     }
728cfca06d7SDimitry Andric     CPU = "pentium";
72901095a5dSDimitry Andric     break;
730cf099d11SDimitry Andric   case 6:
731cf099d11SDimitry Andric     switch (Model) {
73201095a5dSDimitry Andric     case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
733cf099d11SDimitry Andric                // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
734cf099d11SDimitry Andric                // mobile processor, Intel Core 2 Extreme processor, Intel
735cf099d11SDimitry Andric                // Pentium Dual-Core processor, Intel Xeon processor, model
736cf099d11SDimitry Andric                // 0Fh. All processors are manufactured using the 65 nm process.
73701095a5dSDimitry Andric     case 0x16: // Intel Celeron processor model 16h. All processors are
738cf099d11SDimitry Andric                // manufactured using the 65 nm process
739cfca06d7SDimitry Andric       CPU = "core2";
740cfca06d7SDimitry Andric       *Type = X86::INTEL_CORE2;
74101095a5dSDimitry Andric       break;
74201095a5dSDimitry Andric     case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
743cf099d11SDimitry Andric                // 17h. All processors are manufactured using the 45 nm process.
744cf099d11SDimitry Andric                //
745cf099d11SDimitry Andric                // 45nm: Penryn , Wolfdale, Yorkfield (XE)
74601095a5dSDimitry Andric     case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
7475a5ac124SDimitry Andric                // the 45 nm process.
748cfca06d7SDimitry Andric       CPU = "penryn";
749cfca06d7SDimitry Andric       *Type = X86::INTEL_CORE2;
75001095a5dSDimitry Andric       break;
75101095a5dSDimitry Andric     case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
752cf099d11SDimitry Andric                // processors are manufactured using the 45 nm process.
75301095a5dSDimitry Andric     case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
754cf099d11SDimitry Andric                // As found in a Summer 2010 model iMac.
75501095a5dSDimitry Andric     case 0x1f:
75601095a5dSDimitry Andric     case 0x2e:              // Nehalem EX
757cfca06d7SDimitry Andric       CPU = "nehalem";
758cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
759044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_NEHALEM;
76001095a5dSDimitry Andric       break;
76101095a5dSDimitry Andric     case 0x25: // Intel Core i7, laptop version.
76201095a5dSDimitry Andric     case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
76330815c53SDimitry Andric                // processors are manufactured using the 32 nm process.
76401095a5dSDimitry Andric     case 0x2f: // Westmere EX
765cfca06d7SDimitry Andric       CPU = "westmere";
766cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
767044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_WESTMERE;
76801095a5dSDimitry Andric       break;
76901095a5dSDimitry Andric     case 0x2a: // Intel Core i7 processor. All processors are manufactured
770411bd29eSDimitry Andric                // using the 32 nm process.
77101095a5dSDimitry Andric     case 0x2d:
772cfca06d7SDimitry Andric       CPU = "sandybridge";
773cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
774044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
77501095a5dSDimitry Andric       break;
77601095a5dSDimitry Andric     case 0x3a:
77701095a5dSDimitry Andric     case 0x3e:              // Ivy Bridge EP
778cfca06d7SDimitry Andric       CPU = "ivybridge";
779cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
780044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
78101095a5dSDimitry Andric       break;
78258b69754SDimitry Andric 
783f8af5cf6SDimitry Andric     // Haswell:
78401095a5dSDimitry Andric     case 0x3c:
78501095a5dSDimitry Andric     case 0x3f:
78601095a5dSDimitry Andric     case 0x45:
78701095a5dSDimitry Andric     case 0x46:
788cfca06d7SDimitry Andric       CPU = "haswell";
789cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
790044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_HASWELL;
79101095a5dSDimitry Andric       break;
7925a5ac124SDimitry Andric 
7935a5ac124SDimitry Andric     // Broadwell:
79401095a5dSDimitry Andric     case 0x3d:
79501095a5dSDimitry Andric     case 0x47:
79601095a5dSDimitry Andric     case 0x4f:
79701095a5dSDimitry Andric     case 0x56:
798cfca06d7SDimitry Andric       CPU = "broadwell";
799cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
800044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_BROADWELL;
80101095a5dSDimitry Andric       break;
802f8af5cf6SDimitry Andric 
803dd58ef01SDimitry Andric     // Skylake:
8047e7b6700SDimitry Andric     case 0x4e:              // Skylake mobile
8057e7b6700SDimitry Andric     case 0x5e:              // Skylake desktop
8067e7b6700SDimitry Andric     case 0x8e:              // Kaby Lake mobile
8077e7b6700SDimitry Andric     case 0x9e:              // Kaby Lake desktop
808cfca06d7SDimitry Andric     case 0xa5:              // Comet Lake-H/S
809cfca06d7SDimitry Andric     case 0xa6:              // Comet Lake-U
810cfca06d7SDimitry Andric       CPU = "skylake";
811cfca06d7SDimitry Andric       *Type = X86::INTEL_COREI7;
812044eb2f6SDimitry Andric       *Subtype = X86::INTEL_COREI7_SKYLAKE;
81301095a5dSDimitry Andric       break;
814dd58ef01SDimitry Andric 
815344a3780SDimitry Andric     // Rocketlake:
816344a3780SDimitry Andric     case 0xa7:
817344a3780SDimitry Andric       CPU = "rocketlake";
818344a3780SDimitry Andric       *Type = X86::INTEL_COREI7;
819344a3780SDimitry Andric       *Subtype = X86::INTEL_COREI7_ROCKETLAKE;
820344a3780SDimitry Andric       break;
821344a3780SDimitry Andric 
8227e7b6700SDimitry Andric     // Skylake Xeon:
8237e7b6700SDimitry Andric     case 0x55:
824044eb2f6SDimitry Andric       *Type = X86::INTEL_COREI7;
825cfca06d7SDimitry Andric       if (testFeature(X86::FEATURE_AVX512BF16)) {
826cfca06d7SDimitry Andric         CPU = "cooperlake";
827cfca06d7SDimitry Andric         *Subtype = X86::INTEL_COREI7_COOPERLAKE;
828cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
829cfca06d7SDimitry Andric         CPU = "cascadelake";
830cfca06d7SDimitry Andric         *Subtype = X86::INTEL_COREI7_CASCADELAKE;
831cfca06d7SDimitry Andric       } else {
832cfca06d7SDimitry Andric         CPU = "skylake-avx512";
833cfca06d7SDimitry Andric         *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
834cfca06d7SDimitry Andric       }
835044eb2f6SDimitry Andric       break;
836044eb2f6SDimitry Andric 
837044eb2f6SDimitry Andric     // Cannonlake:
838044eb2f6SDimitry Andric     case 0x66:
839cfca06d7SDimitry Andric       CPU = "cannonlake";
840044eb2f6SDimitry Andric       *Type = X86::INTEL_COREI7;
841cfca06d7SDimitry Andric       *Subtype = X86::INTEL_COREI7_CANNONLAKE;
8427e7b6700SDimitry Andric       break;
8437e7b6700SDimitry Andric 
844e6d15924SDimitry Andric     // Icelake:
845e6d15924SDimitry Andric     case 0x7d:
846e6d15924SDimitry Andric     case 0x7e:
847cfca06d7SDimitry Andric       CPU = "icelake-client";
848e6d15924SDimitry Andric       *Type = X86::INTEL_COREI7;
849cfca06d7SDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
850e6d15924SDimitry Andric       break;
851e6d15924SDimitry Andric 
852c0981da4SDimitry Andric     // Tigerlake:
853c0981da4SDimitry Andric     case 0x8c:
854c0981da4SDimitry Andric     case 0x8d:
855c0981da4SDimitry Andric       CPU = "tigerlake";
856c0981da4SDimitry Andric       *Type = X86::INTEL_COREI7;
857c0981da4SDimitry Andric       *Subtype = X86::INTEL_COREI7_TIGERLAKE;
858c0981da4SDimitry Andric       break;
859c0981da4SDimitry Andric 
860c0981da4SDimitry Andric     // Alderlake:
861c0981da4SDimitry Andric     case 0x97:
862c0981da4SDimitry Andric     case 0x9a:
863b1c73532SDimitry Andric     // Gracemont
864b1c73532SDimitry Andric     case 0xbe:
865e3b55780SDimitry Andric     // Raptorlake:
866e3b55780SDimitry Andric     case 0xb7:
867b1c73532SDimitry Andric     case 0xba:
868b1c73532SDimitry Andric     case 0xbf:
869e3b55780SDimitry Andric     // Meteorlake:
870e3b55780SDimitry Andric     case 0xaa:
871e3b55780SDimitry Andric     case 0xac:
872c0981da4SDimitry Andric       CPU = "alderlake";
873c0981da4SDimitry Andric       *Type = X86::INTEL_COREI7;
874c0981da4SDimitry Andric       *Subtype = X86::INTEL_COREI7_ALDERLAKE;
875c0981da4SDimitry Andric       break;
876c0981da4SDimitry Andric 
877b1c73532SDimitry Andric     // Arrowlake:
878b1c73532SDimitry Andric     case 0xc5:
879b1c73532SDimitry Andric       CPU = "arrowlake";
880b1c73532SDimitry Andric       *Type = X86::INTEL_COREI7;
881b1c73532SDimitry Andric       *Subtype = X86::INTEL_COREI7_ARROWLAKE;
882b1c73532SDimitry Andric       break;
883b1c73532SDimitry Andric 
884b1c73532SDimitry Andric     // Arrowlake S:
885b1c73532SDimitry Andric     case 0xc6:
886b1c73532SDimitry Andric     // Lunarlake:
887b1c73532SDimitry Andric     case 0xbd:
888b1c73532SDimitry Andric       CPU = "arrowlake-s";
889b1c73532SDimitry Andric       *Type = X86::INTEL_COREI7;
890b1c73532SDimitry Andric       *Subtype = X86::INTEL_COREI7_ARROWLAKE_S;
891b1c73532SDimitry Andric       break;
892b1c73532SDimitry Andric 
893b1c73532SDimitry Andric     // Pantherlake:
894b1c73532SDimitry Andric     case 0xcc:
895b1c73532SDimitry Andric       CPU = "pantherlake";
896b1c73532SDimitry Andric       *Type = X86::INTEL_COREI7;
897b1c73532SDimitry Andric       *Subtype = X86::INTEL_COREI7_PANTHERLAKE;
898b1c73532SDimitry Andric       break;
899b1c73532SDimitry Andric 
900e3b55780SDimitry Andric     // Graniterapids:
901e3b55780SDimitry Andric     case 0xad:
902e3b55780SDimitry Andric       CPU = "graniterapids";
903e3b55780SDimitry Andric       *Type = X86::INTEL_COREI7;
904e3b55780SDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS;
905e3b55780SDimitry Andric       break;
906e3b55780SDimitry Andric 
9077fa27ce4SDimitry Andric     // Granite Rapids D:
9087fa27ce4SDimitry Andric     case 0xae:
9097fa27ce4SDimitry Andric       CPU = "graniterapids-d";
9107fa27ce4SDimitry Andric       *Type = X86::INTEL_COREI7;
9117fa27ce4SDimitry Andric       *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D;
9127fa27ce4SDimitry Andric       break;
9137fa27ce4SDimitry Andric 
914e6d15924SDimitry Andric     // Icelake Xeon:
915e6d15924SDimitry Andric     case 0x6a:
916e6d15924SDimitry Andric     case 0x6c:
917cfca06d7SDimitry Andric       CPU = "icelake-server";
918e6d15924SDimitry Andric       *Type = X86::INTEL_COREI7;
919cfca06d7SDimitry Andric       *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER;
920e6d15924SDimitry Andric       break;
921e6d15924SDimitry Andric 
922e3b55780SDimitry Andric     // Emerald Rapids:
923e3b55780SDimitry Andric     case 0xcf:
924b60736ecSDimitry Andric     // Sapphire Rapids:
925b60736ecSDimitry Andric     case 0x8f:
926b60736ecSDimitry Andric       CPU = "sapphirerapids";
927b60736ecSDimitry Andric       *Type = X86::INTEL_COREI7;
928b60736ecSDimitry Andric       *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS;
929b60736ecSDimitry Andric       break;
930b60736ecSDimitry Andric 
93101095a5dSDimitry Andric     case 0x1c: // Most 45 nm Intel Atom processors
93201095a5dSDimitry Andric     case 0x26: // 45 nm Atom Lincroft
93301095a5dSDimitry Andric     case 0x27: // 32 nm Atom Medfield
93401095a5dSDimitry Andric     case 0x35: // 32 nm Atom Midview
93501095a5dSDimitry Andric     case 0x36: // 32 nm Atom Midview
936cfca06d7SDimitry Andric       CPU = "bonnell";
937044eb2f6SDimitry Andric       *Type = X86::INTEL_BONNELL;
938cfca06d7SDimitry Andric       break;
939cf099d11SDimitry Andric 
940f8af5cf6SDimitry Andric     // Atom Silvermont codes from the Intel software optimization guide.
94101095a5dSDimitry Andric     case 0x37:
94201095a5dSDimitry Andric     case 0x4a:
94301095a5dSDimitry Andric     case 0x4d:
94401095a5dSDimitry Andric     case 0x5a:
94501095a5dSDimitry Andric     case 0x5d:
94601095a5dSDimitry Andric     case 0x4c: // really airmont
947cfca06d7SDimitry Andric       CPU = "silvermont";
948044eb2f6SDimitry Andric       *Type = X86::INTEL_SILVERMONT;
949cfca06d7SDimitry Andric       break;
9509df3605dSDimitry Andric     // Goldmont:
951044eb2f6SDimitry Andric     case 0x5c: // Apollo Lake
952044eb2f6SDimitry Andric     case 0x5f: // Denverton
953cfca06d7SDimitry Andric       CPU = "goldmont";
954044eb2f6SDimitry Andric       *Type = X86::INTEL_GOLDMONT;
955cfca06d7SDimitry Andric       break;
956eb11fae6SDimitry Andric     case 0x7a:
957cfca06d7SDimitry Andric       CPU = "goldmont-plus";
958eb11fae6SDimitry Andric       *Type = X86::INTEL_GOLDMONT_PLUS;
959eb11fae6SDimitry Andric       break;
960e6d15924SDimitry Andric     case 0x86:
961b1c73532SDimitry Andric     case 0x8a: // Lakefield
962b1c73532SDimitry Andric     case 0x96: // Elkhart Lake
963b1c73532SDimitry Andric     case 0x9c: // Jasper Lake
964b60736ecSDimitry Andric       CPU = "tremont";
965e6d15924SDimitry Andric       *Type = X86::INTEL_TREMONT;
966e6d15924SDimitry Andric       break;
967e6d15924SDimitry Andric 
968e3b55780SDimitry Andric     // Sierraforest:
969e3b55780SDimitry Andric     case 0xaf:
970e3b55780SDimitry Andric       CPU = "sierraforest";
971e3b55780SDimitry Andric       *Type = X86::INTEL_SIERRAFOREST;
972e3b55780SDimitry Andric       break;
973e3b55780SDimitry Andric 
974e3b55780SDimitry Andric     // Grandridge:
975e3b55780SDimitry Andric     case 0xb6:
976e3b55780SDimitry Andric       CPU = "grandridge";
977e3b55780SDimitry Andric       *Type = X86::INTEL_GRANDRIDGE;
978e3b55780SDimitry Andric       break;
979e3b55780SDimitry Andric 
980b1c73532SDimitry Andric     // Clearwaterforest:
981b1c73532SDimitry Andric     case 0xdd:
982b1c73532SDimitry Andric       CPU = "clearwaterforest";
983b1c73532SDimitry Andric       *Type = X86::INTEL_CLEARWATERFOREST;
984b1c73532SDimitry Andric       break;
985b1c73532SDimitry Andric 
986b60736ecSDimitry Andric     // Xeon Phi (Knights Landing + Knights Mill):
98701095a5dSDimitry Andric     case 0x57:
988b60736ecSDimitry Andric       CPU = "knl";
989cfca06d7SDimitry Andric       *Type = X86::INTEL_KNL;
990044eb2f6SDimitry Andric       break;
991044eb2f6SDimitry Andric     case 0x85:
992cfca06d7SDimitry Andric       CPU = "knm";
993cfca06d7SDimitry Andric       *Type = X86::INTEL_KNM;
99401095a5dSDimitry Andric       break;
995f8af5cf6SDimitry Andric 
9965a5ac124SDimitry Andric     default: // Unknown family 6 CPU, try to guess.
997cfca06d7SDimitry Andric       // Don't both with Type/Subtype here, they aren't used by the caller.
998cfca06d7SDimitry Andric       // They're used above to keep the code in sync with compiler-rt.
999cfca06d7SDimitry Andric       // TODO detect tigerlake host from model
1000cfca06d7SDimitry Andric       if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) {
1001cfca06d7SDimitry Andric         CPU = "tigerlake";
1002cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI2)) {
1003cfca06d7SDimitry Andric         CPU = "icelake-client";
1004cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VBMI)) {
1005cfca06d7SDimitry Andric         CPU = "cannonlake";
1006cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512BF16)) {
1007cfca06d7SDimitry Andric         CPU = "cooperlake";
1008cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VNNI)) {
1009cfca06d7SDimitry Andric         CPU = "cascadelake";
1010cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX512VL)) {
1011cfca06d7SDimitry Andric         CPU = "skylake-avx512";
1012cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) {
1013cfca06d7SDimitry Andric         if (testFeature(X86::FEATURE_SHA))
1014cfca06d7SDimitry Andric           CPU = "goldmont";
1015cfca06d7SDimitry Andric         else
1016cfca06d7SDimitry Andric           CPU = "skylake";
1017cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_ADX)) {
1018cfca06d7SDimitry Andric         CPU = "broadwell";
1019cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX2)) {
1020cfca06d7SDimitry Andric         CPU = "haswell";
1021cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_AVX)) {
1022cfca06d7SDimitry Andric         CPU = "sandybridge";
1023cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_2)) {
1024cfca06d7SDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
1025cfca06d7SDimitry Andric           CPU = "silvermont";
1026cfca06d7SDimitry Andric         else
1027cfca06d7SDimitry Andric           CPU = "nehalem";
1028cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSE4_1)) {
1029cfca06d7SDimitry Andric         CPU = "penryn";
1030cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSSE3)) {
1031cfca06d7SDimitry Andric         if (testFeature(X86::FEATURE_MOVBE))
1032cfca06d7SDimitry Andric           CPU = "bonnell";
1033cfca06d7SDimitry Andric         else
1034cfca06d7SDimitry Andric           CPU = "core2";
1035cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_64BIT)) {
1036cfca06d7SDimitry Andric         CPU = "core2";
1037cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSE3)) {
1038cfca06d7SDimitry Andric         CPU = "yonah";
1039cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSE2)) {
1040cfca06d7SDimitry Andric         CPU = "pentium-m";
1041cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_SSE)) {
1042cfca06d7SDimitry Andric         CPU = "pentium3";
1043cfca06d7SDimitry Andric       } else if (testFeature(X86::FEATURE_MMX)) {
1044cfca06d7SDimitry Andric         CPU = "pentium2";
104501095a5dSDimitry Andric       } else {
1046cfca06d7SDimitry Andric         CPU = "pentiumpro";
104701095a5dSDimitry Andric       }
104801095a5dSDimitry Andric       break;
104901095a5dSDimitry Andric     }
105001095a5dSDimitry Andric     break;
1051cf099d11SDimitry Andric   case 15: {
1052cfca06d7SDimitry Andric     if (testFeature(X86::FEATURE_64BIT)) {
1053cfca06d7SDimitry Andric       CPU = "nocona";
105401095a5dSDimitry Andric       break;
105501095a5dSDimitry Andric     }
1056cfca06d7SDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
1057cfca06d7SDimitry Andric       CPU = "prescott";
1058044eb2f6SDimitry Andric       break;
1059044eb2f6SDimitry Andric     }
1060cfca06d7SDimitry Andric     CPU = "pentium4";
106101095a5dSDimitry Andric     break;
106201095a5dSDimitry Andric   }
106301095a5dSDimitry Andric   default:
1064cfca06d7SDimitry Andric     break; // Unknown.
1065cf099d11SDimitry Andric   }
1066cf099d11SDimitry Andric 
1067cfca06d7SDimitry Andric   return CPU;
1068cfca06d7SDimitry Andric }
1069cfca06d7SDimitry Andric 
getAMDProcessorTypeAndSubtype(unsigned Family,unsigned Model,const unsigned * Features,unsigned * Type,unsigned * Subtype)1070ac9a064cSDimitry Andric static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
1071ac9a064cSDimitry Andric                                                  unsigned Model,
1072cfca06d7SDimitry Andric                                                  const unsigned *Features,
1073ac9a064cSDimitry Andric                                                  unsigned *Type,
1074ac9a064cSDimitry Andric                                                  unsigned *Subtype) {
1075ac9a064cSDimitry Andric   const char *CPU = 0;
1076cfca06d7SDimitry Andric 
1077cf099d11SDimitry Andric   switch (Family) {
1078cf099d11SDimitry Andric   case 4:
1079cfca06d7SDimitry Andric     CPU = "i486";
108001095a5dSDimitry Andric     break;
1081cf099d11SDimitry Andric   case 5:
1082cfca06d7SDimitry Andric     CPU = "pentium";
1083cf099d11SDimitry Andric     switch (Model) {
1084cf099d11SDimitry Andric     case 6:
1085cf099d11SDimitry Andric     case 7:
1086cfca06d7SDimitry Andric       CPU = "k6";
1087cfca06d7SDimitry Andric       break;
108801095a5dSDimitry Andric     case 8:
1089cfca06d7SDimitry Andric       CPU = "k6-2";
1090cfca06d7SDimitry Andric       break;
109101095a5dSDimitry Andric     case 9:
109201095a5dSDimitry Andric     case 13:
1093cfca06d7SDimitry Andric       CPU = "k6-3";
1094cfca06d7SDimitry Andric       break;
109501095a5dSDimitry Andric     case 10:
1096cfca06d7SDimitry Andric       CPU = "geode";
1097cfca06d7SDimitry Andric       break;
1098cf099d11SDimitry Andric     }
109901095a5dSDimitry Andric     break;
110001095a5dSDimitry Andric   case 6:
1101cfca06d7SDimitry Andric     if (testFeature(X86::FEATURE_SSE)) {
1102cfca06d7SDimitry Andric       CPU = "athlon-xp";
1103cfca06d7SDimitry Andric       break;
1104cf099d11SDimitry Andric     }
1105cfca06d7SDimitry Andric     CPU = "athlon";
1106cfca06d7SDimitry Andric     break;
110701095a5dSDimitry Andric   case 15:
1108cfca06d7SDimitry Andric     if (testFeature(X86::FEATURE_SSE3)) {
1109cfca06d7SDimitry Andric       CPU = "k8-sse3";
1110cfca06d7SDimitry Andric       break;
111101095a5dSDimitry Andric     }
1112cfca06d7SDimitry Andric     CPU = "k8";
1113cfca06d7SDimitry Andric     break;
1114cf099d11SDimitry Andric   case 16:
1115cfca06d7SDimitry Andric     CPU = "amdfam10";
1116044eb2f6SDimitry Andric     *Type = X86::AMDFAM10H; // "amdfam10"
111701095a5dSDimitry Andric     switch (Model) {
111801095a5dSDimitry Andric     case 2:
1119044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM10H_BARCELONA;
112001095a5dSDimitry Andric       break;
112101095a5dSDimitry Andric     case 4:
1122044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM10H_SHANGHAI;
112301095a5dSDimitry Andric       break;
112401095a5dSDimitry Andric     case 8:
1125044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM10H_ISTANBUL;
112601095a5dSDimitry Andric       break;
112701095a5dSDimitry Andric     }
112801095a5dSDimitry Andric     break;
112963faed5bSDimitry Andric   case 20:
1130cfca06d7SDimitry Andric     CPU = "btver1";
1131044eb2f6SDimitry Andric     *Type = X86::AMD_BTVER1;
1132cfca06d7SDimitry Andric     break;
113363faed5bSDimitry Andric   case 21:
1134cfca06d7SDimitry Andric     CPU = "bdver1";
1135044eb2f6SDimitry Andric     *Type = X86::AMDFAM15H;
1136ca089b24SDimitry Andric     if (Model >= 0x60 && Model <= 0x7f) {
1137cfca06d7SDimitry Andric       CPU = "bdver4";
1138044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER4;
1139cfca06d7SDimitry Andric       break; // 60h-7Fh: Excavator
114001095a5dSDimitry Andric     }
114101095a5dSDimitry Andric     if (Model >= 0x30 && Model <= 0x3f) {
1142cfca06d7SDimitry Andric       CPU = "bdver3";
1143044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER3;
1144cfca06d7SDimitry Andric       break; // 30h-3Fh: Steamroller
114501095a5dSDimitry Andric     }
1146eb11fae6SDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
1147cfca06d7SDimitry Andric       CPU = "bdver2";
1148044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER2;
1149cfca06d7SDimitry Andric       break; // 02h, 10h-1Fh: Piledriver
115001095a5dSDimitry Andric     }
115101095a5dSDimitry Andric     if (Model <= 0x0f) {
1152044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM15H_BDVER1;
1153cfca06d7SDimitry Andric       break; // 00h-0Fh: Bulldozer
115401095a5dSDimitry Andric     }
115501095a5dSDimitry Andric     break;
115659d6cff9SDimitry Andric   case 22:
1157cfca06d7SDimitry Andric     CPU = "btver2";
1158044eb2f6SDimitry Andric     *Type = X86::AMD_BTVER2;
1159cfca06d7SDimitry Andric     break;
1160581a6d85SDimitry Andric   case 23:
1161cfca06d7SDimitry Andric     CPU = "znver1";
1162044eb2f6SDimitry Andric     *Type = X86::AMDFAM17H;
116399aabd70SDimitry Andric     if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) ||
116499aabd70SDimitry Andric         (Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) ||
116599aabd70SDimitry Andric         (Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) ||
116699aabd70SDimitry Andric         (Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) ||
116799aabd70SDimitry Andric         (Model >= 0xa0 && Model <= 0xaf)) {
116899aabd70SDimitry Andric       // Family 17h Models 30h-3Fh (Starship) Zen 2
116999aabd70SDimitry Andric       // Family 17h Models 47h (Cardinal) Zen 2
117099aabd70SDimitry Andric       // Family 17h Models 60h-67h (Renoir) Zen 2
117199aabd70SDimitry Andric       // Family 17h Models 68h-6Fh (Lucienne) Zen 2
117299aabd70SDimitry Andric       // Family 17h Models 70h-7Fh (Matisse) Zen 2
117399aabd70SDimitry Andric       // Family 17h Models 84h-87h (ProjectX) Zen 2
117499aabd70SDimitry Andric       // Family 17h Models 90h-97h (VanGogh) Zen 2
117599aabd70SDimitry Andric       // Family 17h Models 98h-9Fh (Mero) Zen 2
117699aabd70SDimitry Andric       // Family 17h Models A0h-AFh (Mendocino) Zen 2
1177cfca06d7SDimitry Andric       CPU = "znver2";
1178e6d15924SDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER2;
117999aabd70SDimitry Andric       break;
1180e6d15924SDimitry Andric     }
118199aabd70SDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) {
118299aabd70SDimitry Andric       // Family 17h Models 10h-1Fh (Raven1) Zen
118399aabd70SDimitry Andric       // Family 17h Models 10h-1Fh (Picasso) Zen+
118499aabd70SDimitry Andric       // Family 17h Models 20h-2Fh (Raven2 x86) Zen
1185044eb2f6SDimitry Andric       *Subtype = X86::AMDFAM17H_ZNVER1;
118699aabd70SDimitry Andric       break;
1187e6d15924SDimitry Andric     }
1188581a6d85SDimitry Andric     break;
1189b60736ecSDimitry Andric   case 25:
1190b60736ecSDimitry Andric     CPU = "znver3";
1191b60736ecSDimitry Andric     *Type = X86::AMDFAM19H;
119277dbea07SDimitry Andric     if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||
119399aabd70SDimitry Andric         (Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||
119499aabd70SDimitry Andric         (Model >= 0x50 && Model <= 0x5f)) {
119599aabd70SDimitry Andric       // Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3
119699aabd70SDimitry Andric       // Family 19h Models 20h-2Fh (Vermeer) Zen 3
119799aabd70SDimitry Andric       // Family 19h Models 30h-3Fh (Badami) Zen 3
119899aabd70SDimitry Andric       // Family 19h Models 40h-4Fh (Rembrandt) Zen 3+
119999aabd70SDimitry Andric       // Family 19h Models 50h-5Fh (Cezanne) Zen 3
1200b60736ecSDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER3;
1201b60736ecSDimitry Andric       break;
1202e3b55780SDimitry Andric     }
120399aabd70SDimitry Andric     if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) ||
120499aabd70SDimitry Andric         (Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) ||
120599aabd70SDimitry Andric         (Model >= 0xa0 && Model <= 0xaf)) {
120699aabd70SDimitry Andric       // Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 4
120799aabd70SDimitry Andric       // Family 19h Models 60h-6Fh (Raphael) Zen 4
120899aabd70SDimitry Andric       // Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 4
120999aabd70SDimitry Andric       // Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 4
121099aabd70SDimitry Andric       // Family 19h Models A0h-AFh (Stones-Dense) Zen 4
1211e3b55780SDimitry Andric       CPU = "znver4";
1212e3b55780SDimitry Andric       *Subtype = X86::AMDFAM19H_ZNVER4;
1213e3b55780SDimitry Andric       break; //  "znver4"
1214e3b55780SDimitry Andric     }
1215ac9a064cSDimitry Andric     break; // family 19h
12161de139fdSDimitry Andric   case 26:
12171de139fdSDimitry Andric     CPU = "znver5";
12181de139fdSDimitry Andric     *Type = X86::AMDFAM1AH;
12191de139fdSDimitry Andric     if (Model <= 0x77) {
12201de139fdSDimitry Andric       // Models 00h-0Fh (Breithorn).
12211de139fdSDimitry Andric       // Models 10h-1Fh (Breithorn-Dense).
12221de139fdSDimitry Andric       // Models 20h-2Fh (Strix 1).
12231de139fdSDimitry Andric       // Models 30h-37h (Strix 2).
12241de139fdSDimitry Andric       // Models 38h-3Fh (Strix 3).
12251de139fdSDimitry Andric       // Models 40h-4Fh (Granite Ridge).
12261de139fdSDimitry Andric       // Models 50h-5Fh (Weisshorn).
12271de139fdSDimitry Andric       // Models 60h-6Fh (Krackan1).
12281de139fdSDimitry Andric       // Models 70h-77h (Sarlak).
12291de139fdSDimitry Andric       CPU = "znver5";
12301de139fdSDimitry Andric       *Subtype = X86::AMDFAM1AH_ZNVER5;
12311de139fdSDimitry Andric       break; //  "znver5"
12321de139fdSDimitry Andric     }
12331de139fdSDimitry Andric     break;
12341de139fdSDimitry Andric 
123501095a5dSDimitry Andric   default:
1236cfca06d7SDimitry Andric     break; // Unknown AMD CPU.
123701095a5dSDimitry Andric   }
1238cfca06d7SDimitry Andric 
1239cfca06d7SDimitry Andric   return CPU;
124001095a5dSDimitry Andric }
124101095a5dSDimitry Andric 
1242ac9a064cSDimitry Andric #undef testFeature
1243ac9a064cSDimitry Andric 
getAvailableFeatures(unsigned ECX,unsigned EDX,unsigned MaxLeaf,unsigned * Features)1244ca089b24SDimitry Andric static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
1245cfca06d7SDimitry Andric                                  unsigned *Features) {
1246ca089b24SDimitry Andric   unsigned EAX, EBX;
1247ca089b24SDimitry Andric 
1248d8e91e46SDimitry Andric   auto setFeature = [&](unsigned F) {
1249cfca06d7SDimitry Andric     Features[F / 32] |= 1U << (F % 32);
1250d8e91e46SDimitry Andric   };
1251d8e91e46SDimitry Andric 
1252ca089b24SDimitry Andric   if ((EDX >> 15) & 1)
1253d8e91e46SDimitry Andric     setFeature(X86::FEATURE_CMOV);
1254ca089b24SDimitry Andric   if ((EDX >> 23) & 1)
1255d8e91e46SDimitry Andric     setFeature(X86::FEATURE_MMX);
1256ca089b24SDimitry Andric   if ((EDX >> 25) & 1)
1257d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE);
1258ca089b24SDimitry Andric   if ((EDX >> 26) & 1)
1259d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE2);
1260ca089b24SDimitry Andric 
1261ca089b24SDimitry Andric   if ((ECX >> 0) & 1)
1262d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE3);
1263ca089b24SDimitry Andric   if ((ECX >> 1) & 1)
1264d8e91e46SDimitry Andric     setFeature(X86::FEATURE_PCLMUL);
1265ca089b24SDimitry Andric   if ((ECX >> 9) & 1)
1266d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSSE3);
1267ca089b24SDimitry Andric   if ((ECX >> 12) & 1)
1268d8e91e46SDimitry Andric     setFeature(X86::FEATURE_FMA);
1269ca089b24SDimitry Andric   if ((ECX >> 19) & 1)
1270d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE4_1);
1271c0981da4SDimitry Andric   if ((ECX >> 20) & 1) {
1272d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE4_2);
1273c0981da4SDimitry Andric     setFeature(X86::FEATURE_CRC32);
1274c0981da4SDimitry Andric   }
1275ca089b24SDimitry Andric   if ((ECX >> 23) & 1)
1276d8e91e46SDimitry Andric     setFeature(X86::FEATURE_POPCNT);
1277ca089b24SDimitry Andric   if ((ECX >> 25) & 1)
1278d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AES);
1279ca089b24SDimitry Andric 
1280ca089b24SDimitry Andric   if ((ECX >> 22) & 1)
1281d8e91e46SDimitry Andric     setFeature(X86::FEATURE_MOVBE);
128201095a5dSDimitry Andric 
128301095a5dSDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
128401095a5dSDimitry Andric   // indicates that the AVX registers will be saved and restored on context
128501095a5dSDimitry Andric   // switch, then we have full AVX support.
128601095a5dSDimitry Andric   const unsigned AVXBits = (1 << 27) | (1 << 28);
128701095a5dSDimitry Andric   bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
128801095a5dSDimitry Andric                 ((EAX & 0x6) == 0x6);
1289706b4fc4SDimitry Andric #if defined(__APPLE__)
1290706b4fc4SDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1291706b4fc4SDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1292706b4fc4SDimitry Andric   // set right now.
1293706b4fc4SDimitry Andric   bool HasAVX512Save = true;
1294706b4fc4SDimitry Andric #else
1295706b4fc4SDimitry Andric   // AVX512 requires additional context to be saved by the OS.
129601095a5dSDimitry Andric   bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
1297706b4fc4SDimitry Andric #endif
1298ca089b24SDimitry Andric 
1299ca089b24SDimitry Andric   if (HasAVX)
1300d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX);
1301ca089b24SDimitry Andric 
130201095a5dSDimitry Andric   bool HasLeaf7 =
130301095a5dSDimitry Andric       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
130401095a5dSDimitry Andric 
1305ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 3) & 1))
1306d8e91e46SDimitry Andric     setFeature(X86::FEATURE_BMI);
1307ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
1308d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX2);
13091d5ae102SDimitry Andric   if (HasLeaf7 && ((EBX >> 8) & 1))
1310d8e91e46SDimitry Andric     setFeature(X86::FEATURE_BMI2);
1311ac9a064cSDimitry Andric   if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) {
1312d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512F);
1313ac9a064cSDimitry Andric     setFeature(X86::FEATURE_EVEX512);
1314ac9a064cSDimitry Andric   }
1315ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
1316d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512DQ);
1317ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 19) & 1))
1318d8e91e46SDimitry Andric     setFeature(X86::FEATURE_ADX);
1319ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
1320d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512IFMA);
1321044eb2f6SDimitry Andric   if (HasLeaf7 && ((EBX >> 23) & 1))
1322d8e91e46SDimitry Andric     setFeature(X86::FEATURE_CLFLUSHOPT);
1323ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
1324d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512CD);
1325044eb2f6SDimitry Andric   if (HasLeaf7 && ((EBX >> 29) & 1))
1326d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SHA);
1327ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
1328d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512BW);
1329ca089b24SDimitry Andric   if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
1330d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512VL);
1331ca089b24SDimitry Andric 
1332ca089b24SDimitry Andric   if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
1333d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI);
1334d8e91e46SDimitry Andric   if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
1335d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512VBMI2);
1336d8e91e46SDimitry Andric   if (HasLeaf7 && ((ECX >> 8) & 1))
1337d8e91e46SDimitry Andric     setFeature(X86::FEATURE_GFNI);
1338d8e91e46SDimitry Andric   if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
1339d8e91e46SDimitry Andric     setFeature(X86::FEATURE_VPCLMULQDQ);
1340d8e91e46SDimitry Andric   if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
1341d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512VNNI);
1342d8e91e46SDimitry Andric   if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
1343d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512BITALG);
1344ca089b24SDimitry Andric   if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
1345d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
1346ca089b24SDimitry Andric 
1347ca089b24SDimitry Andric   if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
1348d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX5124VNNIW);
1349ca089b24SDimitry Andric   if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
1350d8e91e46SDimitry Andric     setFeature(X86::FEATURE_AVX5124FMAPS);
13511d5ae102SDimitry Andric   if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
13521d5ae102SDimitry Andric     setFeature(X86::FEATURE_AVX512VP2INTERSECT);
13531d5ae102SDimitry Andric 
1354b1c73532SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
1355b1c73532SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
13561d5ae102SDimitry Andric   bool HasLeaf7Subleaf1 =
1357b1c73532SDimitry Andric       HasLeaf7 && EAX >= 1 &&
1358b1c73532SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
13591d5ae102SDimitry Andric   if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
13601d5ae102SDimitry Andric     setFeature(X86::FEATURE_AVX512BF16);
1361ca089b24SDimitry Andric 
1362ca089b24SDimitry Andric   unsigned MaxExtLevel;
1363ca089b24SDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
1364ca089b24SDimitry Andric 
1365ca089b24SDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
1366ca089b24SDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1367ca089b24SDimitry Andric   if (HasExtLeaf1 && ((ECX >> 6) & 1))
1368d8e91e46SDimitry Andric     setFeature(X86::FEATURE_SSE4_A);
1369ca089b24SDimitry Andric   if (HasExtLeaf1 && ((ECX >> 11) & 1))
1370d8e91e46SDimitry Andric     setFeature(X86::FEATURE_XOP);
1371ca089b24SDimitry Andric   if (HasExtLeaf1 && ((ECX >> 16) & 1))
1372d8e91e46SDimitry Andric     setFeature(X86::FEATURE_FMA4);
1373ca089b24SDimitry Andric 
1374ca089b24SDimitry Andric   if (HasExtLeaf1 && ((EDX >> 29) & 1))
1375cfca06d7SDimitry Andric     setFeature(X86::FEATURE_64BIT);
137601095a5dSDimitry Andric }
137701095a5dSDimitry Andric 
getHostCPUName()137801095a5dSDimitry Andric StringRef sys::getHostCPUName() {
1379344a3780SDimitry Andric   unsigned MaxLeaf = 0;
1380344a3780SDimitry Andric   const VendorSignatures Vendor = getVendorSignature(&MaxLeaf);
1381344a3780SDimitry Andric   if (Vendor == VendorSignatures::UNKNOWN)
1382344a3780SDimitry Andric     return "generic";
1383344a3780SDimitry Andric 
138401095a5dSDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
1385ca089b24SDimitry Andric   getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
138601095a5dSDimitry Andric 
138701095a5dSDimitry Andric   unsigned Family = 0, Model = 0;
1388cfca06d7SDimitry Andric   unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0};
138901095a5dSDimitry Andric   detectX86FamilyModel(EAX, &Family, &Model);
1390cfca06d7SDimitry Andric   getAvailableFeatures(ECX, EDX, MaxLeaf, Features);
139101095a5dSDimitry Andric 
1392cfca06d7SDimitry Andric   // These aren't consumed in this file, but we try to keep some source code the
1393cfca06d7SDimitry Andric   // same or similar to compiler-rt.
1394044eb2f6SDimitry Andric   unsigned Type = 0;
1395044eb2f6SDimitry Andric   unsigned Subtype = 0;
139601095a5dSDimitry Andric 
1397cfca06d7SDimitry Andric   StringRef CPU;
1398cfca06d7SDimitry Andric 
1399344a3780SDimitry Andric   if (Vendor == VendorSignatures::GENUINE_INTEL) {
1400cfca06d7SDimitry Andric     CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type,
1401cfca06d7SDimitry Andric                                           &Subtype);
1402344a3780SDimitry Andric   } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) {
1403cfca06d7SDimitry Andric     CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type,
1404cfca06d7SDimitry Andric                                         &Subtype);
140501095a5dSDimitry Andric   }
1406044eb2f6SDimitry Andric 
1407cfca06d7SDimitry Andric   if (!CPU.empty())
1408cfca06d7SDimitry Andric     return CPU;
1409044eb2f6SDimitry Andric 
1410cf099d11SDimitry Andric   return "generic";
1411cf099d11SDimitry Andric }
141201095a5dSDimitry Andric 
1413e3b55780SDimitry Andric #elif defined(__APPLE__) && defined(__powerpc__)
getHostCPUName()14145ca98fd9SDimitry Andric StringRef sys::getHostCPUName() {
141558b69754SDimitry Andric   host_basic_info_data_t hostInfo;
141658b69754SDimitry Andric   mach_msg_type_number_t infoCount;
141758b69754SDimitry Andric 
141858b69754SDimitry Andric   infoCount = HOST_BASIC_INFO_COUNT;
1419d8e91e46SDimitry Andric   mach_port_t hostPort = mach_host_self();
1420d8e91e46SDimitry Andric   host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
142158b69754SDimitry Andric             &infoCount);
1422d8e91e46SDimitry Andric   mach_port_deallocate(mach_task_self(), hostPort);
142358b69754SDimitry Andric 
142401095a5dSDimitry Andric   if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
142501095a5dSDimitry Andric     return "generic";
142658b69754SDimitry Andric 
142758b69754SDimitry Andric   switch (hostInfo.cpu_subtype) {
142801095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_601:
142901095a5dSDimitry Andric     return "601";
143001095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_602:
143101095a5dSDimitry Andric     return "602";
143201095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603:
143301095a5dSDimitry Andric     return "603";
143401095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603e:
143501095a5dSDimitry Andric     return "603e";
143601095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_603ev:
143701095a5dSDimitry Andric     return "603ev";
143801095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604:
143901095a5dSDimitry Andric     return "604";
144001095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_604e:
144101095a5dSDimitry Andric     return "604e";
144201095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_620:
144301095a5dSDimitry Andric     return "620";
144401095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_750:
144501095a5dSDimitry Andric     return "750";
144601095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7400:
144701095a5dSDimitry Andric     return "7400";
144801095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_7450:
144901095a5dSDimitry Andric     return "7450";
145001095a5dSDimitry Andric   case CPU_SUBTYPE_POWERPC_970:
145101095a5dSDimitry Andric     return "970";
145258b69754SDimitry Andric   default:;
145358b69754SDimitry Andric   }
145458b69754SDimitry Andric 
145558b69754SDimitry Andric   return "generic";
145658b69754SDimitry Andric }
1457e3b55780SDimitry Andric #elif defined(__linux__) && defined(__powerpc__)
getHostCPUName()14585ca98fd9SDimitry Andric StringRef sys::getHostCPUName() {
145971d5a254SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1460eb11fae6SDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
146171d5a254SDimitry Andric   return detail::getHostCPUNameForPowerPC(Content);
146258b69754SDimitry Andric }
146371d5a254SDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
getHostCPUName()14645ca98fd9SDimitry Andric StringRef sys::getHostCPUName() {
146571d5a254SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1466eb11fae6SDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
146771d5a254SDimitry Andric   return detail::getHostCPUNameForARM(Content);
146858b69754SDimitry Andric }
1469f8af5cf6SDimitry Andric #elif defined(__linux__) && defined(__s390x__)
getHostCPUName()14705ca98fd9SDimitry Andric StringRef sys::getHostCPUName() {
147171d5a254SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1472eb11fae6SDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
147371d5a254SDimitry Andric   return detail::getHostCPUNameForS390x(Content);
1474f8af5cf6SDimitry Andric }
1475344a3780SDimitry Andric #elif defined(__MVS__)
getHostCPUName()1476344a3780SDimitry Andric StringRef sys::getHostCPUName() {
1477344a3780SDimitry Andric   // Get pointer to Communications Vector Table (CVT).
1478344a3780SDimitry Andric   // The pointer is located at offset 16 of the Prefixed Save Area (PSA).
1479344a3780SDimitry Andric   // It is stored as 31 bit pointer and will be zero-extended to 64 bit.
1480344a3780SDimitry Andric   int *StartToCVTOffset = reinterpret_cast<int *>(0x10);
1481344a3780SDimitry Andric   // Since its stored as a 31-bit pointer, get the 4 bytes from the start
1482344a3780SDimitry Andric   // of address.
1483344a3780SDimitry Andric   int ReadValue = *StartToCVTOffset;
1484344a3780SDimitry Andric   // Explicitly clear the high order bit.
1485344a3780SDimitry Andric   ReadValue = (ReadValue & 0x7FFFFFFF);
1486344a3780SDimitry Andric   char *CVT = reinterpret_cast<char *>(ReadValue);
1487344a3780SDimitry Andric   // The model number is located in the CVT prefix at offset -6 and stored as
1488344a3780SDimitry Andric   // signless packed decimal.
1489344a3780SDimitry Andric   uint16_t Id = *(uint16_t *)&CVT[-6];
1490344a3780SDimitry Andric   // Convert number to integer.
1491344a3780SDimitry Andric   Id = decodePackedBCD<uint16_t>(Id, false);
1492344a3780SDimitry Andric   // Check for vector support. It's stored in field CVTFLAG5 (offset 244),
1493344a3780SDimitry Andric   // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector
1494344a3780SDimitry Andric   // extension can only be used if bit CVTVEF is on.
1495344a3780SDimitry Andric   bool HaveVectorSupport = CVT[244] & 0x80;
1496344a3780SDimitry Andric   return getCPUNameFromS390Model(Id, HaveVectorSupport);
1497344a3780SDimitry Andric }
1498145449b1SDimitry Andric #elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
1499145449b1SDimitry Andric #define CPUFAMILY_ARM_SWIFT 0x1e2d6381
1500145449b1SDimitry Andric #define CPUFAMILY_ARM_CYCLONE 0x37a09642
1501145449b1SDimitry Andric #define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
1502145449b1SDimitry Andric #define CPUFAMILY_ARM_TWISTER 0x92fb37c8
1503145449b1SDimitry Andric #define CPUFAMILY_ARM_HURRICANE 0x67ceee93
1504145449b1SDimitry Andric #define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
1505145449b1SDimitry Andric #define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
1506145449b1SDimitry Andric #define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
1507145449b1SDimitry Andric #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
1508ac9a064cSDimitry Andric #define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d
1509ac9a064cSDimitry Andric #define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
1510706b4fc4SDimitry Andric 
getHostCPUName()1511145449b1SDimitry Andric StringRef sys::getHostCPUName() {
1512145449b1SDimitry Andric   uint32_t Family;
1513145449b1SDimitry Andric   size_t Length = sizeof(Family);
1514145449b1SDimitry Andric   sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);
1515706b4fc4SDimitry Andric 
1516145449b1SDimitry Andric   switch (Family) {
1517145449b1SDimitry Andric   case CPUFAMILY_ARM_SWIFT:
1518706b4fc4SDimitry Andric     return "swift";
1519145449b1SDimitry Andric   case CPUFAMILY_ARM_CYCLONE:
1520145449b1SDimitry Andric     return "apple-a7";
1521145449b1SDimitry Andric   case CPUFAMILY_ARM_TYPHOON:
1522145449b1SDimitry Andric     return "apple-a8";
1523145449b1SDimitry Andric   case CPUFAMILY_ARM_TWISTER:
1524145449b1SDimitry Andric     return "apple-a9";
1525145449b1SDimitry Andric   case CPUFAMILY_ARM_HURRICANE:
1526145449b1SDimitry Andric     return "apple-a10";
1527145449b1SDimitry Andric   case CPUFAMILY_ARM_MONSOON_MISTRAL:
1528145449b1SDimitry Andric     return "apple-a11";
1529145449b1SDimitry Andric   case CPUFAMILY_ARM_VORTEX_TEMPEST:
1530145449b1SDimitry Andric     return "apple-a12";
1531145449b1SDimitry Andric   case CPUFAMILY_ARM_LIGHTNING_THUNDER:
1532145449b1SDimitry Andric     return "apple-a13";
1533145449b1SDimitry Andric   case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
1534145449b1SDimitry Andric     return "apple-m1";
1535ac9a064cSDimitry Andric   case CPUFAMILY_ARM_BLIZZARD_AVALANCHE:
1536ac9a064cSDimitry Andric     return "apple-m2";
1537ac9a064cSDimitry Andric   case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
1538ac9a064cSDimitry Andric     return "apple-m3";
1539145449b1SDimitry Andric   default:
1540145449b1SDimitry Andric     // Default to the newest CPU we know about.
1541ac9a064cSDimitry Andric     return "apple-m3";
1542706b4fc4SDimitry Andric   }
1543706b4fc4SDimitry Andric }
1544344a3780SDimitry Andric #elif defined(_AIX)
getHostCPUName()1545344a3780SDimitry Andric StringRef sys::getHostCPUName() {
1546344a3780SDimitry Andric   switch (_system_configuration.implementation) {
1547344a3780SDimitry Andric   case POWER_4:
1548344a3780SDimitry Andric     if (_system_configuration.version == PV_4_3)
1549344a3780SDimitry Andric       return "970";
1550344a3780SDimitry Andric     return "pwr4";
1551344a3780SDimitry Andric   case POWER_5:
1552344a3780SDimitry Andric     if (_system_configuration.version == PV_5)
1553344a3780SDimitry Andric       return "pwr5";
1554344a3780SDimitry Andric     return "pwr5x";
1555344a3780SDimitry Andric   case POWER_6:
1556344a3780SDimitry Andric     if (_system_configuration.version == PV_6_Compat)
1557344a3780SDimitry Andric       return "pwr6";
1558344a3780SDimitry Andric     return "pwr6x";
1559344a3780SDimitry Andric   case POWER_7:
1560344a3780SDimitry Andric     return "pwr7";
1561344a3780SDimitry Andric   case POWER_8:
1562344a3780SDimitry Andric     return "pwr8";
1563344a3780SDimitry Andric   case POWER_9:
1564344a3780SDimitry Andric     return "pwr9";
1565344a3780SDimitry Andric // TODO: simplify this once the macro is available in all OS levels.
1566344a3780SDimitry Andric #ifdef POWER_10
1567344a3780SDimitry Andric   case POWER_10:
1568344a3780SDimitry Andric #else
1569344a3780SDimitry Andric   case 0x40000:
1570344a3780SDimitry Andric #endif
1571344a3780SDimitry Andric     return "pwr10";
1572c76260f3SDimitry Andric #ifdef POWER_11
1573c76260f3SDimitry Andric   case POWER_11:
1574c76260f3SDimitry Andric #else
1575c76260f3SDimitry Andric   case 0x80000:
1576c76260f3SDimitry Andric #endif
1577c76260f3SDimitry Andric     return "pwr11";
1578344a3780SDimitry Andric   default:
1579344a3780SDimitry Andric     return "generic";
1580344a3780SDimitry Andric   }
1581344a3780SDimitry Andric }
15827fa27ce4SDimitry Andric #elif defined(__loongarch__)
getHostCPUName()15837fa27ce4SDimitry Andric StringRef sys::getHostCPUName() {
15847fa27ce4SDimitry Andric   // Use processor id to detect cpu name.
15857fa27ce4SDimitry Andric   uint32_t processor_id;
15867fa27ce4SDimitry Andric   __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));
1587aca2e42cSDimitry Andric   // Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h.
1588aca2e42cSDimitry Andric   switch (processor_id & 0xf000) {
15897fa27ce4SDimitry Andric   case 0xc000: // Loongson 64bit, 4-issue
15907fa27ce4SDimitry Andric     return "la464";
1591ac9a064cSDimitry Andric   case 0xd000: // Loongson 64bit, 6-issue
1592ac9a064cSDimitry Andric     return "la664";
15937fa27ce4SDimitry Andric   // TODO: Others.
15947fa27ce4SDimitry Andric   default:
15957fa27ce4SDimitry Andric     break;
15967fa27ce4SDimitry Andric   }
15977fa27ce4SDimitry Andric   return "generic";
15987fa27ce4SDimitry Andric }
1599c0981da4SDimitry Andric #elif defined(__riscv)
getHostCPUName()1600c0981da4SDimitry Andric StringRef sys::getHostCPUName() {
1601145449b1SDimitry Andric #if defined(__linux__)
1602145449b1SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1603145449b1SDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1604ac9a064cSDimitry Andric   StringRef Name = detail::getHostCPUNameForRISCV(Content);
1605ac9a064cSDimitry Andric   if (!Name.empty())
1606ac9a064cSDimitry Andric     return Name;
1607ac9a064cSDimitry Andric #endif
1608c0981da4SDimitry Andric #if __riscv_xlen == 64
1609c0981da4SDimitry Andric   return "generic-rv64";
1610c0981da4SDimitry Andric #elif __riscv_xlen == 32
1611c0981da4SDimitry Andric   return "generic-rv32";
1612c0981da4SDimitry Andric #else
1613c0981da4SDimitry Andric #error "Unhandled value of __riscv_xlen"
1614c0981da4SDimitry Andric #endif
1615c0981da4SDimitry Andric }
1616e3b55780SDimitry Andric #elif defined(__sparc__)
1617e3b55780SDimitry Andric #if defined(__linux__)
getHostCPUNameForSPARC(StringRef ProcCpuinfoContent)1618e3b55780SDimitry Andric StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {
1619e3b55780SDimitry Andric   SmallVector<StringRef> Lines;
1620e3b55780SDimitry Andric   ProcCpuinfoContent.split(Lines, "\n");
1621e3b55780SDimitry Andric 
1622e3b55780SDimitry Andric   // Look for cpu line to determine cpu name
1623e3b55780SDimitry Andric   StringRef Cpu;
1624e3b55780SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
1625312c0ed1SDimitry Andric     if (Lines[I].starts_with("cpu")) {
1626e3b55780SDimitry Andric       Cpu = Lines[I].substr(5).ltrim("\t :");
1627e3b55780SDimitry Andric       break;
1628e3b55780SDimitry Andric     }
1629e3b55780SDimitry Andric   }
1630e3b55780SDimitry Andric 
1631e3b55780SDimitry Andric   return StringSwitch<const char *>(Cpu)
1632e3b55780SDimitry Andric       .StartsWith("SuperSparc", "supersparc")
1633e3b55780SDimitry Andric       .StartsWith("HyperSparc", "hypersparc")
1634e3b55780SDimitry Andric       .StartsWith("SpitFire", "ultrasparc")
1635e3b55780SDimitry Andric       .StartsWith("BlackBird", "ultrasparc")
1636e3b55780SDimitry Andric       .StartsWith("Sabre", " ultrasparc")
1637e3b55780SDimitry Andric       .StartsWith("Hummingbird", "ultrasparc")
1638e3b55780SDimitry Andric       .StartsWith("Cheetah", "ultrasparc3")
1639e3b55780SDimitry Andric       .StartsWith("Jalapeno", "ultrasparc3")
1640e3b55780SDimitry Andric       .StartsWith("Jaguar", "ultrasparc3")
1641e3b55780SDimitry Andric       .StartsWith("Panther", "ultrasparc3")
1642e3b55780SDimitry Andric       .StartsWith("Serrano", "ultrasparc3")
1643e3b55780SDimitry Andric       .StartsWith("UltraSparc T1", "niagara")
1644e3b55780SDimitry Andric       .StartsWith("UltraSparc T2", "niagara2")
1645e3b55780SDimitry Andric       .StartsWith("UltraSparc T3", "niagara3")
1646e3b55780SDimitry Andric       .StartsWith("UltraSparc T4", "niagara4")
1647e3b55780SDimitry Andric       .StartsWith("UltraSparc T5", "niagara4")
1648e3b55780SDimitry Andric       .StartsWith("LEON", "leon3")
1649e3b55780SDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1650e3b55780SDimitry Andric       .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */)
1651e3b55780SDimitry Andric       .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */)
1652e3b55780SDimitry Andric       .StartsWith("SPARC-M8", "niagara4" /* "m8" */)
1653e3b55780SDimitry Andric       .Default("generic");
1654e3b55780SDimitry Andric }
1655e3b55780SDimitry Andric #endif
1656e3b55780SDimitry Andric 
getHostCPUName()1657e3b55780SDimitry Andric StringRef sys::getHostCPUName() {
1658e3b55780SDimitry Andric #if defined(__linux__)
1659e3b55780SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
1660e3b55780SDimitry Andric   StringRef Content = P ? P->getBuffer() : "";
1661e3b55780SDimitry Andric   return detail::getHostCPUNameForSPARC(Content);
1662e3b55780SDimitry Andric #elif defined(__sun__) && defined(__svr4__)
1663e3b55780SDimitry Andric   char *buf = NULL;
1664e3b55780SDimitry Andric   kstat_ctl_t *kc;
1665e3b55780SDimitry Andric   kstat_t *ksp;
1666e3b55780SDimitry Andric   kstat_named_t *brand = NULL;
1667e3b55780SDimitry Andric 
1668e3b55780SDimitry Andric   kc = kstat_open();
1669e3b55780SDimitry Andric   if (kc != NULL) {
1670e3b55780SDimitry Andric     ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);
1671e3b55780SDimitry Andric     if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&
1672e3b55780SDimitry Andric         ksp->ks_type == KSTAT_TYPE_NAMED)
1673e3b55780SDimitry Andric       brand =
1674e3b55780SDimitry Andric           (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));
1675e3b55780SDimitry Andric     if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
1676e3b55780SDimitry Andric       buf = KSTAT_NAMED_STR_PTR(brand);
1677e3b55780SDimitry Andric   }
1678e3b55780SDimitry Andric   kstat_close(kc);
1679e3b55780SDimitry Andric 
1680e3b55780SDimitry Andric   return StringSwitch<const char *>(buf)
1681e3b55780SDimitry Andric       .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I
1682e3b55780SDimitry Andric       .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I
1683e3b55780SDimitry Andric       .Case("TMS390Z55",
1684e3b55780SDimitry Andric             "supersparc") // Texas Instruments SuperSPARC I with SuperCache
1685e3b55780SDimitry Andric       .Case("MB86904", "supersparc") // Fujitsu microSPARC II
1686e3b55780SDimitry Andric       .Case("MB86907", "supersparc") // Fujitsu TurboSPARC
1687e3b55780SDimitry Andric       .Case("RT623", "hypersparc")   // Ross hyperSPARC
1688e3b55780SDimitry Andric       .Case("RT625", "hypersparc")
1689e3b55780SDimitry Andric       .Case("RT626", "hypersparc")
1690e3b55780SDimitry Andric       .Case("UltraSPARC-I", "ultrasparc")
1691e3b55780SDimitry Andric       .Case("UltraSPARC-II", "ultrasparc")
1692e3b55780SDimitry Andric       .Case("UltraSPARC-IIe", "ultrasparc")
1693e3b55780SDimitry Andric       .Case("UltraSPARC-IIi", "ultrasparc")
1694e3b55780SDimitry Andric       .Case("SPARC64-III", "ultrasparc")
1695e3b55780SDimitry Andric       .Case("SPARC64-IV", "ultrasparc")
1696e3b55780SDimitry Andric       .Case("UltraSPARC-III", "ultrasparc3")
1697e3b55780SDimitry Andric       .Case("UltraSPARC-III+", "ultrasparc3")
1698e3b55780SDimitry Andric       .Case("UltraSPARC-IIIi", "ultrasparc3")
1699e3b55780SDimitry Andric       .Case("UltraSPARC-IIIi+", "ultrasparc3")
1700e3b55780SDimitry Andric       .Case("UltraSPARC-IV", "ultrasparc3")
1701e3b55780SDimitry Andric       .Case("UltraSPARC-IV+", "ultrasparc3")
1702e3b55780SDimitry Andric       .Case("SPARC64-V", "ultrasparc3")
1703e3b55780SDimitry Andric       .Case("SPARC64-VI", "ultrasparc3")
1704e3b55780SDimitry Andric       .Case("SPARC64-VII", "ultrasparc3")
1705e3b55780SDimitry Andric       .Case("UltraSPARC-T1", "niagara")
1706e3b55780SDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1707e3b55780SDimitry Andric       .Case("UltraSPARC-T2", "niagara2")
1708e3b55780SDimitry Andric       .Case("UltraSPARC-T2+", "niagara2")
1709e3b55780SDimitry Andric       .Case("SPARC-T3", "niagara3")
1710e3b55780SDimitry Andric       .Case("SPARC-T4", "niagara4")
1711e3b55780SDimitry Andric       .Case("SPARC-T5", "niagara4")
1712e3b55780SDimitry Andric       // niagara7/m8 not supported by LLVM yet.
1713e3b55780SDimitry Andric       .Case("SPARC-M7", "niagara4" /* "niagara7" */)
1714e3b55780SDimitry Andric       .Case("SPARC-S7", "niagara4" /* "niagara7" */)
1715e3b55780SDimitry Andric       .Case("SPARC-M8", "niagara4" /* "m8" */)
1716e3b55780SDimitry Andric       .Default("generic");
1717e3b55780SDimitry Andric #else
1718e3b55780SDimitry Andric   return "generic";
1719e3b55780SDimitry Andric #endif
1720e3b55780SDimitry Andric }
1721cf099d11SDimitry Andric #else
getHostCPUName()172201095a5dSDimitry Andric StringRef sys::getHostCPUName() { return "generic"; }
1723344a3780SDimitry Andric namespace llvm {
1724344a3780SDimitry Andric namespace sys {
1725344a3780SDimitry Andric namespace detail {
1726344a3780SDimitry Andric namespace x86 {
1727344a3780SDimitry Andric 
getVendorSignature(unsigned * MaxLeaf)1728344a3780SDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
1729344a3780SDimitry Andric   return VendorSignatures::UNKNOWN;
1730344a3780SDimitry Andric }
1731344a3780SDimitry Andric 
1732344a3780SDimitry Andric } // namespace x86
1733344a3780SDimitry Andric } // namespace detail
1734344a3780SDimitry Andric } // namespace sys
1735344a3780SDimitry Andric } // namespace llvm
1736cf099d11SDimitry Andric #endif
1737cf099d11SDimitry Andric 
1738b915e9e0SDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \
1739b915e9e0SDimitry Andric     defined(__x86_64__) || defined(_M_X64)
getHostCPUFeatures()1740ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
17415a5ac124SDimitry Andric   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
17425a5ac124SDimitry Andric   unsigned MaxLevel;
1743ac9a064cSDimitry Andric   StringMap<bool> Features;
17445a5ac124SDimitry Andric 
1745cfca06d7SDimitry Andric   if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1)
1746ac9a064cSDimitry Andric     return Features;
17475a5ac124SDimitry Andric 
174801095a5dSDimitry Andric   getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
17495a5ac124SDimitry Andric 
1750e6d15924SDimitry Andric   Features["cx8"]    = (EDX >>  8) & 1;
17515a5ac124SDimitry Andric   Features["cmov"]   = (EDX >> 15) & 1;
17525a5ac124SDimitry Andric   Features["mmx"]    = (EDX >> 23) & 1;
1753e6d15924SDimitry Andric   Features["fxsr"]   = (EDX >> 24) & 1;
17545a5ac124SDimitry Andric   Features["sse"]    = (EDX >> 25) & 1;
17555a5ac124SDimitry Andric   Features["sse2"]   = (EDX >> 26) & 1;
1756044eb2f6SDimitry Andric 
17575a5ac124SDimitry Andric   Features["sse3"]   = (ECX >>  0) & 1;
1758044eb2f6SDimitry Andric   Features["pclmul"] = (ECX >>  1) & 1;
17595a5ac124SDimitry Andric   Features["ssse3"]  = (ECX >>  9) & 1;
1760044eb2f6SDimitry Andric   Features["cx16"]   = (ECX >> 13) & 1;
17615a5ac124SDimitry Andric   Features["sse4.1"] = (ECX >> 19) & 1;
17625a5ac124SDimitry Andric   Features["sse4.2"] = (ECX >> 20) & 1;
1763c0981da4SDimitry Andric   Features["crc32"]  = Features["sse4.2"];
17645a5ac124SDimitry Andric   Features["movbe"]  = (ECX >> 22) & 1;
17655a5ac124SDimitry Andric   Features["popcnt"] = (ECX >> 23) & 1;
17665a5ac124SDimitry Andric   Features["aes"]    = (ECX >> 25) & 1;
17675a5ac124SDimitry Andric   Features["rdrnd"]  = (ECX >> 30) & 1;
17685a5ac124SDimitry Andric 
17695a5ac124SDimitry Andric   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
17705a5ac124SDimitry Andric   // indicates that the AVX registers will be saved and restored on context
17715a5ac124SDimitry Andric   // switch, then we have full AVX support.
1772cfca06d7SDimitry Andric   bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
1773cfca06d7SDimitry Andric   bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);
1774706b4fc4SDimitry Andric #if defined(__APPLE__)
1775706b4fc4SDimitry Andric   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
1776706b4fc4SDimitry Andric   // save the AVX512 context if we use AVX512 instructions, even the bit is not
1777706b4fc4SDimitry Andric   // set right now.
1778706b4fc4SDimitry Andric   bool HasAVX512Save = true;
1779706b4fc4SDimitry Andric #else
17805a5ac124SDimitry Andric   // AVX512 requires additional context to be saved by the OS.
1781dd58ef01SDimitry Andric   bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
1782706b4fc4SDimitry Andric #endif
1783cfca06d7SDimitry Andric   // AMX requires additional context to be saved by the OS.
1784cfca06d7SDimitry Andric   const unsigned AMXBits = (1 << 17) | (1 << 18);
1785cfca06d7SDimitry Andric   bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
17865a5ac124SDimitry Andric 
1787044eb2f6SDimitry Andric   Features["avx"]   = HasAVXSave;
1788044eb2f6SDimitry Andric   Features["fma"]   = ((ECX >> 12) & 1) && HasAVXSave;
1789044eb2f6SDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1790044eb2f6SDimitry Andric   Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
1791044eb2f6SDimitry Andric   Features["f16c"]  = ((ECX >> 29) & 1) && HasAVXSave;
1792044eb2f6SDimitry Andric 
17935a5ac124SDimitry Andric   unsigned MaxExtLevel;
179401095a5dSDimitry Andric   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
17955a5ac124SDimitry Andric 
17965a5ac124SDimitry Andric   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
179701095a5dSDimitry Andric                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
1798eb11fae6SDimitry Andric   Features["sahf"]   = HasExtLeaf1 && ((ECX >>  0) & 1);
17995a5ac124SDimitry Andric   Features["lzcnt"]  = HasExtLeaf1 && ((ECX >>  5) & 1);
18005a5ac124SDimitry Andric   Features["sse4a"]  = HasExtLeaf1 && ((ECX >>  6) & 1);
18015a5ac124SDimitry Andric   Features["prfchw"] = HasExtLeaf1 && ((ECX >>  8) & 1);
1802dd58ef01SDimitry Andric   Features["xop"]    = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
1803148779dfSDimitry Andric   Features["lwp"]    = HasExtLeaf1 && ((ECX >> 15) & 1);
1804dd58ef01SDimitry Andric   Features["fma4"]   = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
18055a5ac124SDimitry Andric   Features["tbm"]    = HasExtLeaf1 && ((ECX >> 21) & 1);
180601095a5dSDimitry Andric   Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
18075a5ac124SDimitry Andric 
1808d8e91e46SDimitry Andric   Features["64bit"]  = HasExtLeaf1 && ((EDX >> 29) & 1);
1809d8e91e46SDimitry Andric 
1810eb11fae6SDimitry Andric   // Miscellaneous memory related features, detected by
1811eb11fae6SDimitry Andric   // using the 0x80000008 leaf of the CPUID instruction
181271d5a254SDimitry Andric   bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
1813044eb2f6SDimitry Andric                      !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
181471d5a254SDimitry Andric   Features["clzero"]   = HasExtLeaf8 && ((EBX >> 0) & 1);
1815e3b55780SDimitry Andric   Features["rdpru"]    = HasExtLeaf8 && ((EBX >> 4) & 1);
1816eb11fae6SDimitry Andric   Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
181771d5a254SDimitry Andric 
181801095a5dSDimitry Andric   bool HasLeaf7 =
181901095a5dSDimitry Andric       MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
18205a5ac124SDimitry Andric 
18215a5ac124SDimitry Andric   Features["fsgsbase"]   = HasLeaf7 && ((EBX >>  0) & 1);
182201095a5dSDimitry Andric   Features["sgx"]        = HasLeaf7 && ((EBX >>  2) & 1);
18235a5ac124SDimitry Andric   Features["bmi"]        = HasLeaf7 && ((EBX >>  3) & 1);
1824044eb2f6SDimitry Andric   // AVX2 is only supported if we have the OS save support from AVX.
1825044eb2f6SDimitry Andric   Features["avx2"]       = HasLeaf7 && ((EBX >>  5) & 1) && HasAVXSave;
18265a5ac124SDimitry Andric   Features["bmi2"]       = HasLeaf7 && ((EBX >>  8) & 1);
1827eb11fae6SDimitry Andric   Features["invpcid"]    = HasLeaf7 && ((EBX >> 10) & 1);
18285a5ac124SDimitry Andric   Features["rtm"]        = HasLeaf7 && ((EBX >> 11) & 1);
18295a5ac124SDimitry Andric   // AVX512 is only supported if the OS supports the context save for it.
18305a5ac124SDimitry Andric   Features["avx512f"]    = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
1831ac9a064cSDimitry Andric   if (Features["avx512f"])
1832ac9a064cSDimitry Andric     Features["evex512"]  = true;
18335a5ac124SDimitry Andric   Features["avx512dq"]   = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
1834044eb2f6SDimitry Andric   Features["rdseed"]     = HasLeaf7 && ((EBX >> 18) & 1);
1835044eb2f6SDimitry Andric   Features["adx"]        = HasLeaf7 && ((EBX >> 19) & 1);
183601095a5dSDimitry Andric   Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
1837044eb2f6SDimitry Andric   Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
1838044eb2f6SDimitry Andric   Features["clwb"]       = HasLeaf7 && ((EBX >> 24) & 1);
18395a5ac124SDimitry Andric   Features["avx512cd"]   = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
1840044eb2f6SDimitry Andric   Features["sha"]        = HasLeaf7 && ((EBX >> 29) & 1);
18415a5ac124SDimitry Andric   Features["avx512bw"]   = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
18425a5ac124SDimitry Andric   Features["avx512vl"]   = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
18435a5ac124SDimitry Andric 
184401095a5dSDimitry Andric   Features["avx512vbmi"]      = HasLeaf7 && ((ECX >>  1) & 1) && HasAVX512Save;
184501095a5dSDimitry Andric   Features["pku"]             = HasLeaf7 && ((ECX >>  4) & 1);
1846eb11fae6SDimitry Andric   Features["waitpkg"]         = HasLeaf7 && ((ECX >>  5) & 1);
1847044eb2f6SDimitry Andric   Features["avx512vbmi2"]     = HasLeaf7 && ((ECX >>  6) & 1) && HasAVX512Save;
1848044eb2f6SDimitry Andric   Features["shstk"]           = HasLeaf7 && ((ECX >>  7) & 1);
1849044eb2f6SDimitry Andric   Features["gfni"]            = HasLeaf7 && ((ECX >>  8) & 1);
1850044eb2f6SDimitry Andric   Features["vaes"]            = HasLeaf7 && ((ECX >>  9) & 1) && HasAVXSave;
1851044eb2f6SDimitry Andric   Features["vpclmulqdq"]      = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
1852044eb2f6SDimitry Andric   Features["avx512vnni"]      = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
1853044eb2f6SDimitry Andric   Features["avx512bitalg"]    = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
1854044eb2f6SDimitry Andric   Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
1855eb11fae6SDimitry Andric   Features["rdpid"]           = HasLeaf7 && ((ECX >> 22) & 1);
1856b60736ecSDimitry Andric   Features["kl"]              = HasLeaf7 && ((ECX >> 23) & 1); // key locker
1857eb11fae6SDimitry Andric   Features["cldemote"]        = HasLeaf7 && ((ECX >> 25) & 1);
1858eb11fae6SDimitry Andric   Features["movdiri"]         = HasLeaf7 && ((ECX >> 27) & 1);
1859eb11fae6SDimitry Andric   Features["movdir64b"]       = HasLeaf7 && ((ECX >> 28) & 1);
1860e6d15924SDimitry Andric   Features["enqcmd"]          = HasLeaf7 && ((ECX >> 29) & 1);
1861eb11fae6SDimitry Andric 
1862b60736ecSDimitry Andric   Features["uintr"]           = HasLeaf7 && ((EDX >> 5) & 1);
1863cfca06d7SDimitry Andric   Features["avx512vp2intersect"] =
1864cfca06d7SDimitry Andric       HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save;
1865cfca06d7SDimitry Andric   Features["serialize"]       = HasLeaf7 && ((EDX >> 14) & 1);
1866cfca06d7SDimitry Andric   Features["tsxldtrk"]        = HasLeaf7 && ((EDX >> 16) & 1);
1867eb11fae6SDimitry Andric   // There are two CPUID leafs which information associated with the pconfig
1868eb11fae6SDimitry Andric   // instruction:
1869eb11fae6SDimitry Andric   // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
1870eb11fae6SDimitry Andric   // bit of EDX), while the EAX=0x1b leaf returns information on the
1871eb11fae6SDimitry Andric   // availability of specific pconfig leafs.
1872eb11fae6SDimitry Andric   // The target feature here only refers to the the first of these two.
1873eb11fae6SDimitry Andric   // Users might need to check for the availability of specific pconfig
1874eb11fae6SDimitry Andric   // leaves using cpuid, since that information is ignored while
1875eb11fae6SDimitry Andric   // detecting features using the "-march=native" flag.
1876eb11fae6SDimitry Andric   // For more info, see X86 ISA docs.
1877eb11fae6SDimitry Andric   Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
1878cfca06d7SDimitry Andric   Features["amx-bf16"]   = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;
1879c0981da4SDimitry Andric   Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save;
1880cfca06d7SDimitry Andric   Features["amx-tile"]   = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;
1881cfca06d7SDimitry Andric   Features["amx-int8"]   = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;
1882b1c73532SDimitry Andric   // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
1883b1c73532SDimitry Andric   // return all 0s for invalid subleaves so check the limit.
1884e6d15924SDimitry Andric   bool HasLeaf7Subleaf1 =
1885b1c73532SDimitry Andric       HasLeaf7 && EAX >= 1 &&
1886b1c73532SDimitry Andric       !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
18877fa27ce4SDimitry Andric   Features["sha512"]     = HasLeaf7Subleaf1 && ((EAX >> 0) & 1);
18887fa27ce4SDimitry Andric   Features["sm3"]        = HasLeaf7Subleaf1 && ((EAX >> 1) & 1);
18897fa27ce4SDimitry Andric   Features["sm4"]        = HasLeaf7Subleaf1 && ((EAX >> 2) & 1);
1890e3b55780SDimitry Andric   Features["raoint"]     = HasLeaf7Subleaf1 && ((EAX >> 3) & 1);
1891b60736ecSDimitry Andric   Features["avxvnni"]    = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave;
1892e6d15924SDimitry Andric   Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;
1893e3b55780SDimitry Andric   Features["amx-fp16"]   = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave;
1894e3b55780SDimitry Andric   Features["cmpccxadd"]  = HasLeaf7Subleaf1 && ((EAX >> 7) & 1);
1895b60736ecSDimitry Andric   Features["hreset"]     = HasLeaf7Subleaf1 && ((EAX >> 22) & 1);
1896e3b55780SDimitry Andric   Features["avxifma"]    = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave;
1897e3b55780SDimitry Andric   Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave;
1898e3b55780SDimitry Andric   Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave;
18997fa27ce4SDimitry Andric   Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;
19007fa27ce4SDimitry Andric   Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;
1901e3b55780SDimitry Andric   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
1902b1c73532SDimitry Andric   Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);
1903b1c73532SDimitry Andric   Features["avx10.1-256"] = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
1904ac9a064cSDimitry Andric   bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);
1905ac9a064cSDimitry Andric   Features["egpr"] = HasAPXF;
1906ac9a064cSDimitry Andric   Features["push2pop2"] = HasAPXF;
1907ac9a064cSDimitry Andric   Features["ppx"] = HasAPXF;
1908ac9a064cSDimitry Andric   Features["ndd"] = HasAPXF;
1909ac9a064cSDimitry Andric   Features["ccmp"] = HasAPXF;
1910ac9a064cSDimitry Andric   Features["cf"] = HasAPXF;
191101095a5dSDimitry Andric 
1912dd58ef01SDimitry Andric   bool HasLeafD = MaxLevel >= 0xd &&
191301095a5dSDimitry Andric                   !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
1914dd58ef01SDimitry Andric 
1915dd58ef01SDimitry Andric   // Only enable XSAVE if OS has enabled support for saving YMM state.
1916044eb2f6SDimitry Andric   Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
1917044eb2f6SDimitry Andric   Features["xsavec"]   = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
1918044eb2f6SDimitry Andric   Features["xsaves"]   = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
1919dd58ef01SDimitry Andric 
1920eb11fae6SDimitry Andric   bool HasLeaf14 = MaxLevel >= 0x14 &&
1921eb11fae6SDimitry Andric                   !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
1922eb11fae6SDimitry Andric 
1923eb11fae6SDimitry Andric   Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
1924eb11fae6SDimitry Andric 
1925b60736ecSDimitry Andric   bool HasLeaf19 =
1926b60736ecSDimitry Andric       MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);
1927b60736ecSDimitry Andric   Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1);
1928b60736ecSDimitry Andric 
1929b1c73532SDimitry Andric   bool HasLeaf24 =
1930b1c73532SDimitry Andric       MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);
1931b1c73532SDimitry Andric   Features["avx10.1-512"] =
1932b1c73532SDimitry Andric       Features["avx10.1-256"] && HasLeaf24 && ((EBX >> 18) & 1);
1933b1c73532SDimitry Andric 
1934ac9a064cSDimitry Andric   return Features;
19355a5ac124SDimitry Andric }
19365a5ac124SDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
getHostCPUFeatures()1937ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
1938ac9a064cSDimitry Andric   StringMap<bool> Features;
193971d5a254SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
194071d5a254SDimitry Andric   if (!P)
1941ac9a064cSDimitry Andric     return Features;
19424a16efa3SDimitry Andric 
19434a16efa3SDimitry Andric   SmallVector<StringRef, 32> Lines;
194471d5a254SDimitry Andric   P->getBuffer().split(Lines, "\n");
19454a16efa3SDimitry Andric 
19464a16efa3SDimitry Andric   SmallVector<StringRef, 32> CPUFeatures;
19474a16efa3SDimitry Andric 
19484a16efa3SDimitry Andric   // Look for the CPU features.
19494a16efa3SDimitry Andric   for (unsigned I = 0, E = Lines.size(); I != E; ++I)
1950312c0ed1SDimitry Andric     if (Lines[I].starts_with("Features")) {
1951dd58ef01SDimitry Andric       Lines[I].split(CPUFeatures, ' ');
19524a16efa3SDimitry Andric       break;
19534a16efa3SDimitry Andric     }
19544a16efa3SDimitry Andric 
19555ca98fd9SDimitry Andric #if defined(__aarch64__)
19565ca98fd9SDimitry Andric   // Keep track of which crypto features we have seen
195701095a5dSDimitry Andric   enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
19585ca98fd9SDimitry Andric   uint32_t crypto = 0;
19595ca98fd9SDimitry Andric #endif
19605ca98fd9SDimitry Andric 
19614a16efa3SDimitry Andric   for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
19624a16efa3SDimitry Andric     StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
19635ca98fd9SDimitry Andric #if defined(__aarch64__)
19645ca98fd9SDimitry Andric                                    .Case("asimd", "neon")
19655ca98fd9SDimitry Andric                                    .Case("fp", "fp-armv8")
19665ca98fd9SDimitry Andric                                    .Case("crc32", "crc")
1967145449b1SDimitry Andric                                    .Case("atomics", "lse")
1968145449b1SDimitry Andric                                    .Case("sve", "sve")
1969145449b1SDimitry Andric                                    .Case("sve2", "sve2")
19705ca98fd9SDimitry Andric #else
19714a16efa3SDimitry Andric                                    .Case("half", "fp16")
19724a16efa3SDimitry Andric                                    .Case("neon", "neon")
19734a16efa3SDimitry Andric                                    .Case("vfpv3", "vfp3")
1974e3b55780SDimitry Andric                                    .Case("vfpv3d16", "vfp3d16")
19754a16efa3SDimitry Andric                                    .Case("vfpv4", "vfp4")
19764a16efa3SDimitry Andric                                    .Case("idiva", "hwdiv-arm")
19774a16efa3SDimitry Andric                                    .Case("idivt", "hwdiv")
19785ca98fd9SDimitry Andric #endif
19794a16efa3SDimitry Andric                                    .Default("");
19804a16efa3SDimitry Andric 
19815ca98fd9SDimitry Andric #if defined(__aarch64__)
19825ca98fd9SDimitry Andric     // We need to check crypto separately since we need all of the crypto
19835ca98fd9SDimitry Andric     // extensions to enable the subtarget feature
19845ca98fd9SDimitry Andric     if (CPUFeatures[I] == "aes")
19855ca98fd9SDimitry Andric       crypto |= CAP_AES;
19865ca98fd9SDimitry Andric     else if (CPUFeatures[I] == "pmull")
19875ca98fd9SDimitry Andric       crypto |= CAP_PMULL;
19885ca98fd9SDimitry Andric     else if (CPUFeatures[I] == "sha1")
19895ca98fd9SDimitry Andric       crypto |= CAP_SHA1;
19905ca98fd9SDimitry Andric     else if (CPUFeatures[I] == "sha2")
19915ca98fd9SDimitry Andric       crypto |= CAP_SHA2;
19925ca98fd9SDimitry Andric #endif
19935ca98fd9SDimitry Andric 
19944a16efa3SDimitry Andric     if (LLVMFeatureStr != "")
199567c32a98SDimitry Andric       Features[LLVMFeatureStr] = true;
19964a16efa3SDimitry Andric   }
19974a16efa3SDimitry Andric 
19985ca98fd9SDimitry Andric #if defined(__aarch64__)
19995ca98fd9SDimitry Andric   // If we have all crypto bits we can add the feature
20005ca98fd9SDimitry Andric   if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
200167c32a98SDimitry Andric     Features["crypto"] = true;
20025ca98fd9SDimitry Andric #endif
20035ca98fd9SDimitry Andric 
2004ac9a064cSDimitry Andric   return Features;
20054a16efa3SDimitry Andric }
20061d5ae102SDimitry Andric #elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
getHostCPUFeatures()2007ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
2008ac9a064cSDimitry Andric   StringMap<bool> Features;
2009ac9a064cSDimitry Andric 
20101d5ae102SDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
20111d5ae102SDimitry Andric     Features["neon"] = true;
20121d5ae102SDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
20131d5ae102SDimitry Andric     Features["crc"] = true;
20141d5ae102SDimitry Andric   if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
20151d5ae102SDimitry Andric     Features["crypto"] = true;
20161d5ae102SDimitry Andric 
2017ac9a064cSDimitry Andric   return Features;
20181d5ae102SDimitry Andric }
20197fa27ce4SDimitry Andric #elif defined(__linux__) && defined(__loongarch__)
20207fa27ce4SDimitry Andric #include <sys/auxv.h>
getHostCPUFeatures()2021ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
20227fa27ce4SDimitry Andric   unsigned long hwcap = getauxval(AT_HWCAP);
20237fa27ce4SDimitry Andric   bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU
20247fa27ce4SDimitry Andric   uint32_t cpucfg2 = 0x2;
20257fa27ce4SDimitry Andric   __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));
20267fa27ce4SDimitry Andric 
2027ac9a064cSDimitry Andric   StringMap<bool> Features;
2028ac9a064cSDimitry Andric 
20297fa27ce4SDimitry Andric   Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP
20307fa27ce4SDimitry Andric   Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP
20317fa27ce4SDimitry Andric 
20327fa27ce4SDimitry Andric   Features["lsx"] = hwcap & (1UL << 4);  // HWCAP_LOONGARCH_LSX
20337fa27ce4SDimitry Andric   Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX
20347fa27ce4SDimitry Andric   Features["lvz"] = hwcap & (1UL << 9);  // HWCAP_LOONGARCH_LVZ
20357fa27ce4SDimitry Andric 
2036ac9a064cSDimitry Andric   return Features;
2037ac9a064cSDimitry Andric }
2038ac9a064cSDimitry Andric #elif defined(__linux__) && defined(__riscv)
2039ac9a064cSDimitry Andric // struct riscv_hwprobe
2040ac9a064cSDimitry Andric struct RISCVHwProbe {
2041ac9a064cSDimitry Andric   int64_t Key;
2042ac9a064cSDimitry Andric   uint64_t Value;
2043ac9a064cSDimitry Andric };
getHostCPUFeatures()2044ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() {
2045ac9a064cSDimitry Andric   RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0},
2046ac9a064cSDimitry Andric                        {/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0}};
2047ac9a064cSDimitry Andric   int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query,
2048ac9a064cSDimitry Andric                     /*pair_count=*/std::size(Query), /*cpu_count=*/0,
2049ac9a064cSDimitry Andric                     /*cpus=*/0, /*flags=*/0);
2050ac9a064cSDimitry Andric   if (Ret != 0)
2051ac9a064cSDimitry Andric     return {};
2052ac9a064cSDimitry Andric 
2053ac9a064cSDimitry Andric   StringMap<bool> Features;
2054ac9a064cSDimitry Andric   uint64_t BaseMask = Query[0].Value;
2055ac9a064cSDimitry Andric   // Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set.
2056ac9a064cSDimitry Andric   if (BaseMask & 1) {
2057ac9a064cSDimitry Andric     Features["i"] = true;
2058ac9a064cSDimitry Andric     Features["m"] = true;
2059ac9a064cSDimitry Andric     Features["a"] = true;
2060ac9a064cSDimitry Andric   }
2061ac9a064cSDimitry Andric 
2062ac9a064cSDimitry Andric   uint64_t ExtMask = Query[1].Value;
2063ac9a064cSDimitry Andric   Features["f"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
2064ac9a064cSDimitry Andric   Features["d"] = ExtMask & (1 << 0);           // RISCV_HWPROBE_IMA_FD
2065ac9a064cSDimitry Andric   Features["c"] = ExtMask & (1 << 1);           // RISCV_HWPROBE_IMA_C
2066ac9a064cSDimitry Andric   Features["v"] = ExtMask & (1 << 2);           // RISCV_HWPROBE_IMA_V
2067ac9a064cSDimitry Andric   Features["zba"] = ExtMask & (1 << 3);         // RISCV_HWPROBE_EXT_ZBA
2068ac9a064cSDimitry Andric   Features["zbb"] = ExtMask & (1 << 4);         // RISCV_HWPROBE_EXT_ZBB
2069ac9a064cSDimitry Andric   Features["zbs"] = ExtMask & (1 << 5);         // RISCV_HWPROBE_EXT_ZBS
2070ac9a064cSDimitry Andric   Features["zicboz"] = ExtMask & (1 << 6);      // RISCV_HWPROBE_EXT_ZICBOZ
2071ac9a064cSDimitry Andric   Features["zbc"] = ExtMask & (1 << 7);         // RISCV_HWPROBE_EXT_ZBC
2072ac9a064cSDimitry Andric   Features["zbkb"] = ExtMask & (1 << 8);        // RISCV_HWPROBE_EXT_ZBKB
2073ac9a064cSDimitry Andric   Features["zbkc"] = ExtMask & (1 << 9);        // RISCV_HWPROBE_EXT_ZBKC
2074ac9a064cSDimitry Andric   Features["zbkx"] = ExtMask & (1 << 10);       // RISCV_HWPROBE_EXT_ZBKX
2075ac9a064cSDimitry Andric   Features["zknd"] = ExtMask & (1 << 11);       // RISCV_HWPROBE_EXT_ZKND
2076ac9a064cSDimitry Andric   Features["zkne"] = ExtMask & (1 << 12);       // RISCV_HWPROBE_EXT_ZKNE
2077ac9a064cSDimitry Andric   Features["zknh"] = ExtMask & (1 << 13);       // RISCV_HWPROBE_EXT_ZKNH
2078ac9a064cSDimitry Andric   Features["zksed"] = ExtMask & (1 << 14);      // RISCV_HWPROBE_EXT_ZKSED
2079ac9a064cSDimitry Andric   Features["zksh"] = ExtMask & (1 << 15);       // RISCV_HWPROBE_EXT_ZKSH
2080ac9a064cSDimitry Andric   Features["zkt"] = ExtMask & (1 << 16);        // RISCV_HWPROBE_EXT_ZKT
2081ac9a064cSDimitry Andric   Features["zvbb"] = ExtMask & (1 << 17);       // RISCV_HWPROBE_EXT_ZVBB
2082ac9a064cSDimitry Andric   Features["zvbc"] = ExtMask & (1 << 18);       // RISCV_HWPROBE_EXT_ZVBC
2083ac9a064cSDimitry Andric   Features["zvkb"] = ExtMask & (1 << 19);       // RISCV_HWPROBE_EXT_ZVKB
2084ac9a064cSDimitry Andric   Features["zvkg"] = ExtMask & (1 << 20);       // RISCV_HWPROBE_EXT_ZVKG
2085ac9a064cSDimitry Andric   Features["zvkned"] = ExtMask & (1 << 21);     // RISCV_HWPROBE_EXT_ZVKNED
2086ac9a064cSDimitry Andric   Features["zvknha"] = ExtMask & (1 << 22);     // RISCV_HWPROBE_EXT_ZVKNHA
2087ac9a064cSDimitry Andric   Features["zvknhb"] = ExtMask & (1 << 23);     // RISCV_HWPROBE_EXT_ZVKNHB
2088ac9a064cSDimitry Andric   Features["zvksed"] = ExtMask & (1 << 24);     // RISCV_HWPROBE_EXT_ZVKSED
2089ac9a064cSDimitry Andric   Features["zvksh"] = ExtMask & (1 << 25);      // RISCV_HWPROBE_EXT_ZVKSH
2090ac9a064cSDimitry Andric   Features["zvkt"] = ExtMask & (1 << 26);       // RISCV_HWPROBE_EXT_ZVKT
2091ac9a064cSDimitry Andric   Features["zfh"] = ExtMask & (1 << 27);        // RISCV_HWPROBE_EXT_ZFH
2092ac9a064cSDimitry Andric   Features["zfhmin"] = ExtMask & (1 << 28);     // RISCV_HWPROBE_EXT_ZFHMIN
2093ac9a064cSDimitry Andric   Features["zihintntl"] = ExtMask & (1 << 29);  // RISCV_HWPROBE_EXT_ZIHINTNTL
2094ac9a064cSDimitry Andric   Features["zvfh"] = ExtMask & (1 << 30);       // RISCV_HWPROBE_EXT_ZVFH
2095ac9a064cSDimitry Andric   Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN
2096ac9a064cSDimitry Andric   Features["zfa"] = ExtMask & (1ULL << 32);     // RISCV_HWPROBE_EXT_ZFA
2097ac9a064cSDimitry Andric   Features["ztso"] = ExtMask & (1ULL << 33);    // RISCV_HWPROBE_EXT_ZTSO
2098ac9a064cSDimitry Andric   // TODO: Re-enable zacas when it is marked non-experimental again.
2099ac9a064cSDimitry Andric   // Features["zacas"] = ExtMask & (1ULL << 34);   // RISCV_HWPROBE_EXT_ZACAS
2100ac9a064cSDimitry Andric   Features["zicond"] = ExtMask & (1ULL << 35);  // RISCV_HWPROBE_EXT_ZICOND
2101ac9a064cSDimitry Andric   Features["zihintpause"] =
2102ac9a064cSDimitry Andric       ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE
2103ac9a064cSDimitry Andric 
2104ac9a064cSDimitry Andric   // TODO: set unaligned-scalar-mem if RISCV_HWPROBE_KEY_MISALIGNED_PERF returns
2105ac9a064cSDimitry Andric   // RISCV_HWPROBE_MISALIGNED_FAST.
2106ac9a064cSDimitry Andric 
2107ac9a064cSDimitry Andric   return Features;
21087fa27ce4SDimitry Andric }
21094a16efa3SDimitry Andric #else
getHostCPUFeatures()2110ac9a064cSDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { return {}; }
21114a16efa3SDimitry Andric #endif
21124a16efa3SDimitry Andric 
21137fa27ce4SDimitry Andric #if __APPLE__
21147fa27ce4SDimitry Andric /// \returns the \p triple, but with the Host's arch spliced in.
withHostArch(Triple T)21157fa27ce4SDimitry Andric static Triple withHostArch(Triple T) {
21167fa27ce4SDimitry Andric #if defined(__arm__)
21177fa27ce4SDimitry Andric   T.setArch(Triple::arm);
21187fa27ce4SDimitry Andric   T.setArchName("arm");
21197fa27ce4SDimitry Andric #elif defined(__arm64e__)
21207fa27ce4SDimitry Andric   T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);
21217fa27ce4SDimitry Andric   T.setArchName("arm64e");
21227fa27ce4SDimitry Andric #elif defined(__aarch64__)
21237fa27ce4SDimitry Andric   T.setArch(Triple::aarch64);
21247fa27ce4SDimitry Andric   T.setArchName("arm64");
21257fa27ce4SDimitry Andric #elif defined(__x86_64h__)
21267fa27ce4SDimitry Andric   T.setArch(Triple::x86_64);
21277fa27ce4SDimitry Andric   T.setArchName("x86_64h");
21287fa27ce4SDimitry Andric #elif defined(__x86_64__)
21297fa27ce4SDimitry Andric   T.setArch(Triple::x86_64);
21307fa27ce4SDimitry Andric   T.setArchName("x86_64");
2131b1c73532SDimitry Andric #elif defined(__i386__)
2132b1c73532SDimitry Andric   T.setArch(Triple::x86);
2133b1c73532SDimitry Andric   T.setArchName("i386");
21347fa27ce4SDimitry Andric #elif defined(__powerpc__)
21357fa27ce4SDimitry Andric   T.setArch(Triple::ppc);
21367fa27ce4SDimitry Andric   T.setArchName("powerpc");
21377fa27ce4SDimitry Andric #else
21387fa27ce4SDimitry Andric #  error "Unimplemented host arch fixup"
21397fa27ce4SDimitry Andric #endif
21407fa27ce4SDimitry Andric   return T;
21417fa27ce4SDimitry Andric }
21427fa27ce4SDimitry Andric #endif
21437fa27ce4SDimitry Andric 
getProcessTriple()21444a16efa3SDimitry Andric std::string sys::getProcessTriple() {
2145ca089b24SDimitry Andric   std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
2146ca089b24SDimitry Andric   Triple PT(Triple::normalize(TargetTripleString));
21474a16efa3SDimitry Andric 
21487fa27ce4SDimitry Andric #if __APPLE__
21497fa27ce4SDimitry Andric   /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of
21507fa27ce4SDimitry Andric   /// the slices. This fixes that up.
21517fa27ce4SDimitry Andric   PT = withHostArch(PT);
21527fa27ce4SDimitry Andric #endif
21537fa27ce4SDimitry Andric 
21544a16efa3SDimitry Andric   if (sizeof(void *) == 8 && PT.isArch32Bit())
21554a16efa3SDimitry Andric     PT = PT.get64BitArchVariant();
21564a16efa3SDimitry Andric   if (sizeof(void *) == 4 && PT.isArch64Bit())
21574a16efa3SDimitry Andric     PT = PT.get32BitArchVariant();
21584a16efa3SDimitry Andric 
21594a16efa3SDimitry Andric   return PT.str();
21604a16efa3SDimitry Andric }
2161e3b55780SDimitry Andric 
printDefaultTargetAndDetectedCPU(raw_ostream & OS)2162e3b55780SDimitry Andric void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) {
2163e3b55780SDimitry Andric #if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
2164e3b55780SDimitry Andric   std::string CPU = std::string(sys::getHostCPUName());
2165e3b55780SDimitry Andric   if (CPU == "generic")
2166e3b55780SDimitry Andric     CPU = "(unknown)";
2167e3b55780SDimitry Andric   OS << "  Default target: " << sys::getDefaultTargetTriple() << '\n'
2168e3b55780SDimitry Andric      << "  Host CPU: " << CPU << '\n';
2169e3b55780SDimitry Andric #endif
2170e3b55780SDimitry Andric }
2171