15ffd83dbSDimitry Andric //===-- X86TargetParser - Parser for X86 features ---------------*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This file implements a target parser to recognise X86 hardware features.
105ffd83dbSDimitry Andric //
115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
125ffd83dbSDimitry Andric 
135ffd83dbSDimitry Andric #include "llvm/Support/X86TargetParser.h"
145ffd83dbSDimitry Andric #include "llvm/ADT/Triple.h"
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric using namespace llvm;
175ffd83dbSDimitry Andric using namespace llvm::X86;
185ffd83dbSDimitry Andric 
195ffd83dbSDimitry Andric namespace {
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric /// Container class for CPU features.
225ffd83dbSDimitry Andric /// This is a constexpr reimplementation of a subset of std::bitset. It would be
235ffd83dbSDimitry Andric /// nice to use std::bitset directly, but it doesn't support constant
245ffd83dbSDimitry Andric /// initialization.
255ffd83dbSDimitry Andric class FeatureBitset {
265ffd83dbSDimitry Andric   static constexpr unsigned NUM_FEATURE_WORDS =
275ffd83dbSDimitry Andric       (X86::CPU_FEATURE_MAX + 31) / 32;
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric   // This cannot be a std::array, operator[] is not constexpr until C++17.
305ffd83dbSDimitry Andric   uint32_t Bits[NUM_FEATURE_WORDS] = {};
315ffd83dbSDimitry Andric 
325ffd83dbSDimitry Andric public:
335ffd83dbSDimitry Andric   constexpr FeatureBitset() = default;
FeatureBitset(std::initializer_list<unsigned> Init)345ffd83dbSDimitry Andric   constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
355ffd83dbSDimitry Andric     for (auto I : Init)
365ffd83dbSDimitry Andric       set(I);
375ffd83dbSDimitry Andric   }
385ffd83dbSDimitry Andric 
any() const3975b4d546SDimitry Andric   bool any() const {
4075b4d546SDimitry Andric     return llvm::any_of(Bits, [](uint64_t V) { return V != 0; });
4175b4d546SDimitry Andric   }
4275b4d546SDimitry Andric 
set(unsigned I)435ffd83dbSDimitry Andric   constexpr FeatureBitset &set(unsigned I) {
445ffd83dbSDimitry Andric     // GCC <6.2 crashes if this is written in a single statement.
455ffd83dbSDimitry Andric     uint32_t NewBits = Bits[I / 32] | (uint32_t(1) << (I % 32));
465ffd83dbSDimitry Andric     Bits[I / 32] = NewBits;
475ffd83dbSDimitry Andric     return *this;
485ffd83dbSDimitry Andric   }
495ffd83dbSDimitry Andric 
operator [](unsigned I) const505ffd83dbSDimitry Andric   constexpr bool operator[](unsigned I) const {
515ffd83dbSDimitry Andric     uint32_t Mask = uint32_t(1) << (I % 32);
525ffd83dbSDimitry Andric     return (Bits[I / 32] & Mask) != 0;
535ffd83dbSDimitry Andric   }
545ffd83dbSDimitry Andric 
operator &=(const FeatureBitset & RHS)555ffd83dbSDimitry Andric   constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
565ffd83dbSDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
575ffd83dbSDimitry Andric       // GCC <6.2 crashes if this is written in a single statement.
585ffd83dbSDimitry Andric       uint32_t NewBits = Bits[I] & RHS.Bits[I];
595ffd83dbSDimitry Andric       Bits[I] = NewBits;
605ffd83dbSDimitry Andric     }
615ffd83dbSDimitry Andric     return *this;
625ffd83dbSDimitry Andric   }
635ffd83dbSDimitry Andric 
operator |=(const FeatureBitset & RHS)645ffd83dbSDimitry Andric   constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
655ffd83dbSDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
665ffd83dbSDimitry Andric       // GCC <6.2 crashes if this is written in a single statement.
675ffd83dbSDimitry Andric       uint32_t NewBits = Bits[I] | RHS.Bits[I];
685ffd83dbSDimitry Andric       Bits[I] = NewBits;
695ffd83dbSDimitry Andric     }
705ffd83dbSDimitry Andric     return *this;
715ffd83dbSDimitry Andric   }
725ffd83dbSDimitry Andric 
735ffd83dbSDimitry Andric   // gcc 5.3 miscompiles this if we try to write this using operator&=.
operator &(const FeatureBitset & RHS) const745ffd83dbSDimitry Andric   constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
755ffd83dbSDimitry Andric     FeatureBitset Result;
765ffd83dbSDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
775ffd83dbSDimitry Andric       Result.Bits[I] = Bits[I] & RHS.Bits[I];
785ffd83dbSDimitry Andric     return Result;
795ffd83dbSDimitry Andric   }
805ffd83dbSDimitry Andric 
815ffd83dbSDimitry Andric   // gcc 5.3 miscompiles this if we try to write this using operator&=.
operator |(const FeatureBitset & RHS) const825ffd83dbSDimitry Andric   constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
835ffd83dbSDimitry Andric     FeatureBitset Result;
845ffd83dbSDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
855ffd83dbSDimitry Andric       Result.Bits[I] = Bits[I] | RHS.Bits[I];
865ffd83dbSDimitry Andric     return Result;
875ffd83dbSDimitry Andric   }
885ffd83dbSDimitry Andric 
operator ~() const895ffd83dbSDimitry Andric   constexpr FeatureBitset operator~() const {
905ffd83dbSDimitry Andric     FeatureBitset Result;
915ffd83dbSDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
925ffd83dbSDimitry Andric       Result.Bits[I] = ~Bits[I];
935ffd83dbSDimitry Andric     return Result;
945ffd83dbSDimitry Andric   }
9575b4d546SDimitry Andric 
operator !=(const FeatureBitset & RHS) const9675b4d546SDimitry Andric   constexpr bool operator!=(const FeatureBitset &RHS) const {
9775b4d546SDimitry Andric     for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I)
9875b4d546SDimitry Andric       if (Bits[I] != RHS.Bits[I])
9975b4d546SDimitry Andric         return true;
10075b4d546SDimitry Andric     return false;
10175b4d546SDimitry Andric   }
1025ffd83dbSDimitry Andric };
1035ffd83dbSDimitry Andric 
1045ffd83dbSDimitry Andric struct ProcInfo {
1055ffd83dbSDimitry Andric   StringLiteral Name;
1065ffd83dbSDimitry Andric   X86::CPUKind Kind;
1075ffd83dbSDimitry Andric   unsigned KeyFeature;
1085ffd83dbSDimitry Andric   FeatureBitset Features;
1095ffd83dbSDimitry Andric };
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric struct FeatureInfo {
1125ffd83dbSDimitry Andric   StringLiteral Name;
1135ffd83dbSDimitry Andric   FeatureBitset ImpliedFeatures;
1145ffd83dbSDimitry Andric };
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric } // end anonymous namespace
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric #define X86_FEATURE(ENUM, STRING)                                              \
119af732203SDimitry Andric   constexpr FeatureBitset Feature##ENUM = {X86::FEATURE_##ENUM};
1205ffd83dbSDimitry Andric #include "llvm/Support/X86TargetParser.def"
1215ffd83dbSDimitry Andric 
1225ffd83dbSDimitry Andric // Pentium with MMX.
123af732203SDimitry Andric constexpr FeatureBitset FeaturesPentiumMMX =
1245ffd83dbSDimitry Andric     FeatureX87 | FeatureCMPXCHG8B | FeatureMMX;
1255ffd83dbSDimitry Andric 
1265ffd83dbSDimitry Andric // Pentium 2 and 3.
127af732203SDimitry Andric constexpr FeatureBitset FeaturesPentium2 =
1285ffd83dbSDimitry Andric     FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | FeatureFXSR;
129af732203SDimitry Andric constexpr FeatureBitset FeaturesPentium3 = FeaturesPentium2 | FeatureSSE;
1305ffd83dbSDimitry Andric 
1315ffd83dbSDimitry Andric // Pentium 4 CPUs
132af732203SDimitry Andric constexpr FeatureBitset FeaturesPentium4 = FeaturesPentium3 | FeatureSSE2;
133af732203SDimitry Andric constexpr FeatureBitset FeaturesPrescott = FeaturesPentium4 | FeatureSSE3;
134af732203SDimitry Andric constexpr FeatureBitset FeaturesNocona =
1355ffd83dbSDimitry Andric     FeaturesPrescott | Feature64BIT | FeatureCMPXCHG16B;
1365ffd83dbSDimitry Andric 
1375ffd83dbSDimitry Andric // Basic 64-bit capable CPU.
138af732203SDimitry Andric constexpr FeatureBitset FeaturesX86_64 = FeaturesPentium4 | Feature64BIT;
139af732203SDimitry Andric constexpr FeatureBitset FeaturesX86_64_V2 = FeaturesX86_64 | FeatureSAHF |
140af732203SDimitry Andric                                             FeaturePOPCNT | FeatureSSE4_2 |
141af732203SDimitry Andric                                             FeatureCMPXCHG16B;
142af732203SDimitry Andric constexpr FeatureBitset FeaturesX86_64_V3 =
143af732203SDimitry Andric     FeaturesX86_64_V2 | FeatureAVX2 | FeatureBMI | FeatureBMI2 | FeatureF16C |
144af732203SDimitry Andric     FeatureFMA | FeatureLZCNT | FeatureMOVBE | FeatureXSAVE;
145af732203SDimitry Andric constexpr FeatureBitset FeaturesX86_64_V4 = FeaturesX86_64_V3 |
146af732203SDimitry Andric                                             FeatureAVX512BW | FeatureAVX512CD |
147af732203SDimitry Andric                                             FeatureAVX512DQ | FeatureAVX512VL;
1485ffd83dbSDimitry Andric 
1495ffd83dbSDimitry Andric // Intel Core CPUs
150af732203SDimitry Andric constexpr FeatureBitset FeaturesCore2 =
1515ffd83dbSDimitry Andric     FeaturesNocona | FeatureSAHF | FeatureSSSE3;
152af732203SDimitry Andric constexpr FeatureBitset FeaturesPenryn = FeaturesCore2 | FeatureSSE4_1;
153af732203SDimitry Andric constexpr FeatureBitset FeaturesNehalem =
1545ffd83dbSDimitry Andric     FeaturesPenryn | FeaturePOPCNT | FeatureSSE4_2;
155af732203SDimitry Andric constexpr FeatureBitset FeaturesWestmere = FeaturesNehalem | FeaturePCLMUL;
156af732203SDimitry Andric constexpr FeatureBitset FeaturesSandyBridge =
1575ffd83dbSDimitry Andric     FeaturesWestmere | FeatureAVX | FeatureXSAVE | FeatureXSAVEOPT;
158af732203SDimitry Andric constexpr FeatureBitset FeaturesIvyBridge =
1595ffd83dbSDimitry Andric     FeaturesSandyBridge | FeatureF16C | FeatureFSGSBASE | FeatureRDRND;
160af732203SDimitry Andric constexpr FeatureBitset FeaturesHaswell =
1615ffd83dbSDimitry Andric     FeaturesIvyBridge | FeatureAVX2 | FeatureBMI | FeatureBMI2 | FeatureFMA |
1625ffd83dbSDimitry Andric     FeatureINVPCID | FeatureLZCNT | FeatureMOVBE;
163af732203SDimitry Andric constexpr FeatureBitset FeaturesBroadwell =
1645ffd83dbSDimitry Andric     FeaturesHaswell | FeatureADX | FeaturePRFCHW | FeatureRDSEED;
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric // Intel Knights Landing and Knights Mill
1675ffd83dbSDimitry Andric // Knights Landing has feature parity with Broadwell.
168af732203SDimitry Andric constexpr FeatureBitset FeaturesKNL =
1695ffd83dbSDimitry Andric     FeaturesBroadwell | FeatureAES | FeatureAVX512F | FeatureAVX512CD |
1705ffd83dbSDimitry Andric     FeatureAVX512ER | FeatureAVX512PF | FeaturePREFETCHWT1;
171af732203SDimitry Andric constexpr FeatureBitset FeaturesKNM = FeaturesKNL | FeatureAVX512VPOPCNTDQ;
1725ffd83dbSDimitry Andric 
1735ffd83dbSDimitry Andric // Intel Skylake processors.
174af732203SDimitry Andric constexpr FeatureBitset FeaturesSkylakeClient =
1755ffd83dbSDimitry Andric     FeaturesBroadwell | FeatureAES | FeatureCLFLUSHOPT | FeatureXSAVEC |
1765ffd83dbSDimitry Andric     FeatureXSAVES | FeatureSGX;
1775ffd83dbSDimitry Andric // SkylakeServer inherits all SkylakeClient features except SGX.
1785ffd83dbSDimitry Andric // FIXME: That doesn't match gcc.
179af732203SDimitry Andric constexpr FeatureBitset FeaturesSkylakeServer =
1805ffd83dbSDimitry Andric     (FeaturesSkylakeClient & ~FeatureSGX) | FeatureAVX512F | FeatureAVX512CD |
1815ffd83dbSDimitry Andric     FeatureAVX512DQ | FeatureAVX512BW | FeatureAVX512VL | FeatureCLWB |
1825ffd83dbSDimitry Andric     FeaturePKU;
183af732203SDimitry Andric constexpr FeatureBitset FeaturesCascadeLake =
1845ffd83dbSDimitry Andric     FeaturesSkylakeServer | FeatureAVX512VNNI;
185af732203SDimitry Andric constexpr FeatureBitset FeaturesCooperLake =
1865ffd83dbSDimitry Andric     FeaturesCascadeLake | FeatureAVX512BF16;
1875ffd83dbSDimitry Andric 
1885ffd83dbSDimitry Andric // Intel 10nm processors.
189af732203SDimitry Andric constexpr FeatureBitset FeaturesCannonlake =
1905ffd83dbSDimitry Andric     FeaturesSkylakeClient | FeatureAVX512F | FeatureAVX512CD | FeatureAVX512DQ |
1915ffd83dbSDimitry Andric     FeatureAVX512BW | FeatureAVX512VL | FeatureAVX512IFMA | FeatureAVX512VBMI |
1925ffd83dbSDimitry Andric     FeaturePKU | FeatureSHA;
193af732203SDimitry Andric constexpr FeatureBitset FeaturesICLClient =
1945ffd83dbSDimitry Andric     FeaturesCannonlake | FeatureAVX512BITALG | FeatureAVX512VBMI2 |
195*5f7ddb14SDimitry Andric     FeatureAVX512VNNI | FeatureAVX512VPOPCNTDQ | FeatureGFNI | FeatureRDPID |
196*5f7ddb14SDimitry Andric     FeatureVAES | FeatureVPCLMULQDQ;
197*5f7ddb14SDimitry Andric constexpr FeatureBitset FeaturesRocketlake = FeaturesICLClient & ~FeatureSGX;
198af732203SDimitry Andric constexpr FeatureBitset FeaturesICLServer =
199*5f7ddb14SDimitry Andric     FeaturesICLClient | FeatureCLWB | FeaturePCONFIG | FeatureWBNOINVD;
200af732203SDimitry Andric constexpr FeatureBitset FeaturesTigerlake =
2015ffd83dbSDimitry Andric     FeaturesICLClient | FeatureAVX512VP2INTERSECT | FeatureMOVDIR64B |
202*5f7ddb14SDimitry Andric     FeatureCLWB | FeatureMOVDIRI | FeatureSHSTK | FeatureKL | FeatureWIDEKL;
203af732203SDimitry Andric constexpr FeatureBitset FeaturesSapphireRapids =
204af732203SDimitry Andric     FeaturesICLServer | FeatureAMX_TILE | FeatureAMX_INT8 | FeatureAMX_BF16 |
205af732203SDimitry Andric     FeatureAVX512BF16 | FeatureAVX512VP2INTERSECT | FeatureCLDEMOTE |
206af732203SDimitry Andric     FeatureENQCMD | FeatureMOVDIR64B | FeatureMOVDIRI | FeaturePTWRITE |
207af732203SDimitry Andric     FeatureSERIALIZE | FeatureSHSTK | FeatureTSXLDTRK | FeatureUINTR |
208af732203SDimitry Andric     FeatureWAITPKG | FeatureAVXVNNI;
2095ffd83dbSDimitry Andric 
2105ffd83dbSDimitry Andric // Intel Atom processors.
2115ffd83dbSDimitry Andric // Bonnell has feature parity with Core2 and adds MOVBE.
212af732203SDimitry Andric constexpr FeatureBitset FeaturesBonnell = FeaturesCore2 | FeatureMOVBE;
2135ffd83dbSDimitry Andric // Silvermont has parity with Westmere and Bonnell plus PRFCHW and RDRND.
214af732203SDimitry Andric constexpr FeatureBitset FeaturesSilvermont =
2155ffd83dbSDimitry Andric     FeaturesBonnell | FeaturesWestmere | FeaturePRFCHW | FeatureRDRND;
216af732203SDimitry Andric constexpr FeatureBitset FeaturesGoldmont =
2175ffd83dbSDimitry Andric     FeaturesSilvermont | FeatureAES | FeatureCLFLUSHOPT | FeatureFSGSBASE |
2185ffd83dbSDimitry Andric     FeatureRDSEED | FeatureSHA | FeatureXSAVE | FeatureXSAVEC |
2195ffd83dbSDimitry Andric     FeatureXSAVEOPT | FeatureXSAVES;
220af732203SDimitry Andric constexpr FeatureBitset FeaturesGoldmontPlus =
2215ffd83dbSDimitry Andric     FeaturesGoldmont | FeaturePTWRITE | FeatureRDPID | FeatureSGX;
222af732203SDimitry Andric constexpr FeatureBitset FeaturesTremont =
2235ffd83dbSDimitry Andric     FeaturesGoldmontPlus | FeatureCLWB | FeatureGFNI;
224*5f7ddb14SDimitry Andric constexpr FeatureBitset FeaturesAlderlake =
225*5f7ddb14SDimitry Andric     FeaturesTremont | FeatureADX | FeatureBMI | FeatureBMI2 | FeatureF16C |
226*5f7ddb14SDimitry Andric     FeatureFMA | FeatureINVPCID | FeatureLZCNT | FeaturePCONFIG | FeaturePKU |
227*5f7ddb14SDimitry Andric     FeatureSERIALIZE | FeatureSHSTK | FeatureVAES | FeatureVPCLMULQDQ |
228*5f7ddb14SDimitry Andric     FeatureCLDEMOTE | FeatureMOVDIR64B | FeatureMOVDIRI | FeatureWAITPKG |
229*5f7ddb14SDimitry Andric     FeatureAVXVNNI | FeatureHRESET | FeatureWIDEKL;
2305ffd83dbSDimitry Andric 
2315ffd83dbSDimitry Andric // Geode Processor.
232af732203SDimitry Andric constexpr FeatureBitset FeaturesGeode =
2335ffd83dbSDimitry Andric     FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | Feature3DNOW | Feature3DNOWA;
2345ffd83dbSDimitry Andric 
2355ffd83dbSDimitry Andric // K6 processor.
236af732203SDimitry Andric constexpr FeatureBitset FeaturesK6 = FeatureX87 | FeatureCMPXCHG8B | FeatureMMX;
2375ffd83dbSDimitry Andric 
2385ffd83dbSDimitry Andric // K7 and K8 architecture processors.
239af732203SDimitry Andric constexpr FeatureBitset FeaturesAthlon =
2405ffd83dbSDimitry Andric     FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | Feature3DNOW | Feature3DNOWA;
241af732203SDimitry Andric constexpr FeatureBitset FeaturesAthlonXP =
2425ffd83dbSDimitry Andric     FeaturesAthlon | FeatureFXSR | FeatureSSE;
243af732203SDimitry Andric constexpr FeatureBitset FeaturesK8 =
2445ffd83dbSDimitry Andric     FeaturesAthlonXP | FeatureSSE2 | Feature64BIT;
245af732203SDimitry Andric constexpr FeatureBitset FeaturesK8SSE3 = FeaturesK8 | FeatureSSE3;
246af732203SDimitry Andric constexpr FeatureBitset FeaturesAMDFAM10 =
2475ffd83dbSDimitry Andric     FeaturesK8SSE3 | FeatureCMPXCHG16B | FeatureLZCNT | FeaturePOPCNT |
2485ffd83dbSDimitry Andric     FeaturePRFCHW | FeatureSAHF | FeatureSSE4_A;
2495ffd83dbSDimitry Andric 
2505ffd83dbSDimitry Andric // Bobcat architecture processors.
251af732203SDimitry Andric constexpr FeatureBitset FeaturesBTVER1 =
2525ffd83dbSDimitry Andric     FeatureX87 | FeatureCMPXCHG8B | FeatureCMPXCHG16B | Feature64BIT |
2535ffd83dbSDimitry Andric     FeatureFXSR | FeatureLZCNT | FeatureMMX | FeaturePOPCNT | FeaturePRFCHW |
2545ffd83dbSDimitry Andric     FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 | FeatureSSE4_A |
2555ffd83dbSDimitry Andric     FeatureSAHF;
256af732203SDimitry Andric constexpr FeatureBitset FeaturesBTVER2 =
2575ffd83dbSDimitry Andric     FeaturesBTVER1 | FeatureAES | FeatureAVX | FeatureBMI | FeatureF16C |
2585ffd83dbSDimitry Andric     FeatureMOVBE | FeaturePCLMUL | FeatureXSAVE | FeatureXSAVEOPT;
2595ffd83dbSDimitry Andric 
2605ffd83dbSDimitry Andric // AMD Bulldozer architecture processors.
261af732203SDimitry Andric constexpr FeatureBitset FeaturesBDVER1 =
2625ffd83dbSDimitry Andric     FeatureX87 | FeatureAES | FeatureAVX | FeatureCMPXCHG8B |
2635ffd83dbSDimitry Andric     FeatureCMPXCHG16B | Feature64BIT | FeatureFMA4 | FeatureFXSR | FeatureLWP |
2645ffd83dbSDimitry Andric     FeatureLZCNT | FeatureMMX | FeaturePCLMUL | FeaturePOPCNT | FeaturePRFCHW |
2655ffd83dbSDimitry Andric     FeatureSAHF | FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 |
2665ffd83dbSDimitry Andric     FeatureSSE4_1 | FeatureSSE4_2 | FeatureSSE4_A | FeatureXOP | FeatureXSAVE;
267af732203SDimitry Andric constexpr FeatureBitset FeaturesBDVER2 =
2685ffd83dbSDimitry Andric     FeaturesBDVER1 | FeatureBMI | FeatureFMA | FeatureF16C | FeatureTBM;
269af732203SDimitry Andric constexpr FeatureBitset FeaturesBDVER3 =
2705ffd83dbSDimitry Andric     FeaturesBDVER2 | FeatureFSGSBASE | FeatureXSAVEOPT;
271af732203SDimitry Andric constexpr FeatureBitset FeaturesBDVER4 = FeaturesBDVER3 | FeatureAVX2 |
272af732203SDimitry Andric                                          FeatureBMI2 | FeatureMOVBE |
273af732203SDimitry Andric                                          FeatureMWAITX | FeatureRDRND;
2745ffd83dbSDimitry Andric 
2755ffd83dbSDimitry Andric // AMD Zen architecture processors.
276af732203SDimitry Andric constexpr FeatureBitset FeaturesZNVER1 =
2775ffd83dbSDimitry Andric     FeatureX87 | FeatureADX | FeatureAES | FeatureAVX | FeatureAVX2 |
2785ffd83dbSDimitry Andric     FeatureBMI | FeatureBMI2 | FeatureCLFLUSHOPT | FeatureCLZERO |
2795ffd83dbSDimitry Andric     FeatureCMPXCHG8B | FeatureCMPXCHG16B | Feature64BIT | FeatureF16C |
2805ffd83dbSDimitry Andric     FeatureFMA | FeatureFSGSBASE | FeatureFXSR | FeatureLZCNT | FeatureMMX |
2815ffd83dbSDimitry Andric     FeatureMOVBE | FeatureMWAITX | FeaturePCLMUL | FeaturePOPCNT |
2825ffd83dbSDimitry Andric     FeaturePRFCHW | FeatureRDRND | FeatureRDSEED | FeatureSAHF | FeatureSHA |
2835ffd83dbSDimitry Andric     FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 | FeatureSSE4_1 |
2845ffd83dbSDimitry Andric     FeatureSSE4_2 | FeatureSSE4_A | FeatureXSAVE | FeatureXSAVEC |
2855ffd83dbSDimitry Andric     FeatureXSAVEOPT | FeatureXSAVES;
286af732203SDimitry Andric constexpr FeatureBitset FeaturesZNVER2 =
2875ffd83dbSDimitry Andric     FeaturesZNVER1 | FeatureCLWB | FeatureRDPID | FeatureWBNOINVD;
288af732203SDimitry Andric static constexpr FeatureBitset FeaturesZNVER3 = FeaturesZNVER2 |
289af732203SDimitry Andric                                                 FeatureINVPCID | FeaturePKU |
290af732203SDimitry Andric                                                 FeatureVAES | FeatureVPCLMULQDQ;
2915ffd83dbSDimitry Andric 
292af732203SDimitry Andric constexpr ProcInfo Processors[] = {
2935ffd83dbSDimitry Andric   // Empty processor. Include X87 and CMPXCHG8 for backwards compatibility.
2945ffd83dbSDimitry Andric   { {""}, CK_None, ~0U, FeatureX87 | FeatureCMPXCHG8B },
2955ffd83dbSDimitry Andric   // i386-generation processors.
2965ffd83dbSDimitry Andric   { {"i386"}, CK_i386, ~0U, FeatureX87 },
2975ffd83dbSDimitry Andric   // i486-generation processors.
2985ffd83dbSDimitry Andric   { {"i486"}, CK_i486, ~0U, FeatureX87 },
2995ffd83dbSDimitry Andric   { {"winchip-c6"}, CK_WinChipC6, ~0U, FeaturesPentiumMMX },
3005ffd83dbSDimitry Andric   { {"winchip2"}, CK_WinChip2, ~0U, FeaturesPentiumMMX | Feature3DNOW },
3015ffd83dbSDimitry Andric   { {"c3"}, CK_C3, ~0U, FeaturesPentiumMMX | Feature3DNOW },
3025ffd83dbSDimitry Andric   // i586-generation processors, P5 microarchitecture based.
3035ffd83dbSDimitry Andric   { {"i586"}, CK_i586, ~0U, FeatureX87 | FeatureCMPXCHG8B },
3045ffd83dbSDimitry Andric   { {"pentium"}, CK_Pentium, ~0U, FeatureX87 | FeatureCMPXCHG8B },
3055ffd83dbSDimitry Andric   { {"pentium-mmx"}, CK_PentiumMMX, ~0U, FeaturesPentiumMMX },
3065ffd83dbSDimitry Andric   // i686-generation processors, P6 / Pentium M microarchitecture based.
3075ffd83dbSDimitry Andric   { {"pentiumpro"}, CK_PentiumPro, ~0U, FeatureX87 | FeatureCMPXCHG8B },
3085ffd83dbSDimitry Andric   { {"i686"}, CK_i686, ~0U, FeatureX87 | FeatureCMPXCHG8B },
3095ffd83dbSDimitry Andric   { {"pentium2"}, CK_Pentium2, ~0U, FeaturesPentium2 },
3105ffd83dbSDimitry Andric   { {"pentium3"}, CK_Pentium3, ~0U, FeaturesPentium3 },
3115ffd83dbSDimitry Andric   { {"pentium3m"}, CK_Pentium3, ~0U, FeaturesPentium3 },
3125ffd83dbSDimitry Andric   { {"pentium-m"}, CK_PentiumM, ~0U, FeaturesPentium4 },
3135ffd83dbSDimitry Andric   { {"c3-2"}, CK_C3_2, ~0U, FeaturesPentium3 },
3145ffd83dbSDimitry Andric   { {"yonah"}, CK_Yonah, ~0U, FeaturesPrescott },
3155ffd83dbSDimitry Andric   // Netburst microarchitecture based processors.
3165ffd83dbSDimitry Andric   { {"pentium4"}, CK_Pentium4, ~0U, FeaturesPentium4 },
3175ffd83dbSDimitry Andric   { {"pentium4m"}, CK_Pentium4, ~0U, FeaturesPentium4 },
3185ffd83dbSDimitry Andric   { {"prescott"}, CK_Prescott, ~0U, FeaturesPrescott },
3195ffd83dbSDimitry Andric   { {"nocona"}, CK_Nocona, ~0U, FeaturesNocona },
3205ffd83dbSDimitry Andric   // Core microarchitecture based processors.
3215ffd83dbSDimitry Andric   { {"core2"}, CK_Core2, ~0U, FeaturesCore2 },
3225ffd83dbSDimitry Andric   { {"penryn"}, CK_Penryn, ~0U, FeaturesPenryn },
3235ffd83dbSDimitry Andric   // Atom processors
3245ffd83dbSDimitry Andric   { {"bonnell"}, CK_Bonnell, FEATURE_SSSE3, FeaturesBonnell },
3255ffd83dbSDimitry Andric   { {"atom"}, CK_Bonnell, FEATURE_SSSE3, FeaturesBonnell },
3265ffd83dbSDimitry Andric   { {"silvermont"}, CK_Silvermont, FEATURE_SSE4_2, FeaturesSilvermont },
3275ffd83dbSDimitry Andric   { {"slm"}, CK_Silvermont, FEATURE_SSE4_2, FeaturesSilvermont },
3285ffd83dbSDimitry Andric   { {"goldmont"}, CK_Goldmont, FEATURE_SSE4_2, FeaturesGoldmont },
3295ffd83dbSDimitry Andric   { {"goldmont-plus"}, CK_GoldmontPlus, FEATURE_SSE4_2, FeaturesGoldmontPlus },
3305ffd83dbSDimitry Andric   { {"tremont"}, CK_Tremont, FEATURE_SSE4_2, FeaturesTremont },
3315ffd83dbSDimitry Andric   // Nehalem microarchitecture based processors.
3325ffd83dbSDimitry Andric   { {"nehalem"}, CK_Nehalem, FEATURE_SSE4_2, FeaturesNehalem },
3335ffd83dbSDimitry Andric   { {"corei7"}, CK_Nehalem, FEATURE_SSE4_2, FeaturesNehalem },
3345ffd83dbSDimitry Andric   // Westmere microarchitecture based processors.
3355ffd83dbSDimitry Andric   { {"westmere"}, CK_Westmere, FEATURE_PCLMUL, FeaturesWestmere },
3365ffd83dbSDimitry Andric   // Sandy Bridge microarchitecture based processors.
3375ffd83dbSDimitry Andric   { {"sandybridge"}, CK_SandyBridge, FEATURE_AVX, FeaturesSandyBridge },
3385ffd83dbSDimitry Andric   { {"corei7-avx"}, CK_SandyBridge, FEATURE_AVX, FeaturesSandyBridge },
3395ffd83dbSDimitry Andric   // Ivy Bridge microarchitecture based processors.
3405ffd83dbSDimitry Andric   { {"ivybridge"}, CK_IvyBridge, FEATURE_AVX, FeaturesIvyBridge },
3415ffd83dbSDimitry Andric   { {"core-avx-i"}, CK_IvyBridge, FEATURE_AVX, FeaturesIvyBridge },
3425ffd83dbSDimitry Andric   // Haswell microarchitecture based processors.
3435ffd83dbSDimitry Andric   { {"haswell"}, CK_Haswell, FEATURE_AVX2, FeaturesHaswell },
3445ffd83dbSDimitry Andric   { {"core-avx2"}, CK_Haswell, FEATURE_AVX2, FeaturesHaswell },
3455ffd83dbSDimitry Andric   // Broadwell microarchitecture based processors.
3465ffd83dbSDimitry Andric   { {"broadwell"}, CK_Broadwell, FEATURE_AVX2, FeaturesBroadwell },
3475ffd83dbSDimitry Andric   // Skylake client microarchitecture based processors.
3485ffd83dbSDimitry Andric   { {"skylake"}, CK_SkylakeClient, FEATURE_AVX2, FeaturesSkylakeClient },
3495ffd83dbSDimitry Andric   // Skylake server microarchitecture based processors.
3505ffd83dbSDimitry Andric   { {"skylake-avx512"}, CK_SkylakeServer, FEATURE_AVX512F, FeaturesSkylakeServer },
3515ffd83dbSDimitry Andric   { {"skx"}, CK_SkylakeServer, FEATURE_AVX512F, FeaturesSkylakeServer },
3525ffd83dbSDimitry Andric   // Cascadelake Server microarchitecture based processors.
3535ffd83dbSDimitry Andric   { {"cascadelake"}, CK_Cascadelake, FEATURE_AVX512VNNI, FeaturesCascadeLake },
3545ffd83dbSDimitry Andric   // Cooperlake Server microarchitecture based processors.
3555ffd83dbSDimitry Andric   { {"cooperlake"}, CK_Cooperlake, FEATURE_AVX512BF16, FeaturesCooperLake },
3565ffd83dbSDimitry Andric   // Cannonlake client microarchitecture based processors.
3575ffd83dbSDimitry Andric   { {"cannonlake"}, CK_Cannonlake, FEATURE_AVX512VBMI, FeaturesCannonlake },
3585ffd83dbSDimitry Andric   // Icelake client microarchitecture based processors.
3595ffd83dbSDimitry Andric   { {"icelake-client"}, CK_IcelakeClient, FEATURE_AVX512VBMI2, FeaturesICLClient },
360*5f7ddb14SDimitry Andric   // Rocketlake microarchitecture based processors.
361*5f7ddb14SDimitry Andric   { {"rocketlake"}, CK_Rocketlake, FEATURE_AVX512VBMI2, FeaturesRocketlake },
3625ffd83dbSDimitry Andric   // Icelake server microarchitecture based processors.
3635ffd83dbSDimitry Andric   { {"icelake-server"}, CK_IcelakeServer, FEATURE_AVX512VBMI2, FeaturesICLServer },
3645ffd83dbSDimitry Andric   // Tigerlake microarchitecture based processors.
3655ffd83dbSDimitry Andric   { {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, FeaturesTigerlake },
366af732203SDimitry Andric   // Sapphire Rapids microarchitecture based processors.
367af732203SDimitry Andric   { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512VP2INTERSECT, FeaturesSapphireRapids },
368af732203SDimitry Andric   // Alderlake microarchitecture based processors.
369af732203SDimitry Andric   { {"alderlake"}, CK_Alderlake, FEATURE_AVX2, FeaturesAlderlake },
3705ffd83dbSDimitry Andric   // Knights Landing processor.
3715ffd83dbSDimitry Andric   { {"knl"}, CK_KNL, FEATURE_AVX512F, FeaturesKNL },
3725ffd83dbSDimitry Andric   // Knights Mill processor.
3735ffd83dbSDimitry Andric   { {"knm"}, CK_KNM, FEATURE_AVX5124FMAPS, FeaturesKNM },
3745ffd83dbSDimitry Andric   // Lakemont microarchitecture based processors.
3755ffd83dbSDimitry Andric   { {"lakemont"}, CK_Lakemont, ~0U, FeatureCMPXCHG8B },
3765ffd83dbSDimitry Andric   // K6 architecture processors.
3775ffd83dbSDimitry Andric   { {"k6"}, CK_K6, ~0U, FeaturesK6 },
3785ffd83dbSDimitry Andric   { {"k6-2"}, CK_K6_2, ~0U, FeaturesK6 | Feature3DNOW },
3795ffd83dbSDimitry Andric   { {"k6-3"}, CK_K6_3, ~0U, FeaturesK6 | Feature3DNOW },
3805ffd83dbSDimitry Andric   // K7 architecture processors.
3815ffd83dbSDimitry Andric   { {"athlon"}, CK_Athlon, ~0U, FeaturesAthlon },
3825ffd83dbSDimitry Andric   { {"athlon-tbird"}, CK_Athlon, ~0U, FeaturesAthlon },
3835ffd83dbSDimitry Andric   { {"athlon-xp"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
3845ffd83dbSDimitry Andric   { {"athlon-mp"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
3855ffd83dbSDimitry Andric   { {"athlon-4"}, CK_AthlonXP, ~0U, FeaturesAthlonXP },
3865ffd83dbSDimitry Andric   // K8 architecture processors.
3875ffd83dbSDimitry Andric   { {"k8"}, CK_K8, ~0U, FeaturesK8 },
3885ffd83dbSDimitry Andric   { {"athlon64"}, CK_K8, ~0U, FeaturesK8 },
3895ffd83dbSDimitry Andric   { {"athlon-fx"}, CK_K8, ~0U, FeaturesK8 },
3905ffd83dbSDimitry Andric   { {"opteron"}, CK_K8, ~0U, FeaturesK8 },
3915ffd83dbSDimitry Andric   { {"k8-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
3925ffd83dbSDimitry Andric   { {"athlon64-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
3935ffd83dbSDimitry Andric   { {"opteron-sse3"}, CK_K8SSE3, ~0U, FeaturesK8SSE3 },
3945ffd83dbSDimitry Andric   { {"amdfam10"}, CK_AMDFAM10, FEATURE_SSE4_A, FeaturesAMDFAM10 },
3955ffd83dbSDimitry Andric   { {"barcelona"}, CK_AMDFAM10, FEATURE_SSE4_A, FeaturesAMDFAM10 },
3965ffd83dbSDimitry Andric   // Bobcat architecture processors.
3975ffd83dbSDimitry Andric   { {"btver1"}, CK_BTVER1, FEATURE_SSE4_A, FeaturesBTVER1 },
3985ffd83dbSDimitry Andric   { {"btver2"}, CK_BTVER2, FEATURE_BMI, FeaturesBTVER2 },
3995ffd83dbSDimitry Andric   // Bulldozer architecture processors.
4005ffd83dbSDimitry Andric   { {"bdver1"}, CK_BDVER1, FEATURE_XOP, FeaturesBDVER1 },
4015ffd83dbSDimitry Andric   { {"bdver2"}, CK_BDVER2, FEATURE_FMA, FeaturesBDVER2 },
4025ffd83dbSDimitry Andric   { {"bdver3"}, CK_BDVER3, FEATURE_FMA, FeaturesBDVER3 },
4035ffd83dbSDimitry Andric   { {"bdver4"}, CK_BDVER4, FEATURE_AVX2, FeaturesBDVER4 },
4045ffd83dbSDimitry Andric   // Zen architecture processors.
4055ffd83dbSDimitry Andric   { {"znver1"}, CK_ZNVER1, FEATURE_AVX2, FeaturesZNVER1 },
4065ffd83dbSDimitry Andric   { {"znver2"}, CK_ZNVER2, FEATURE_AVX2, FeaturesZNVER2 },
407af732203SDimitry Andric   { {"znver3"}, CK_ZNVER3, FEATURE_AVX2, FeaturesZNVER3 },
4085ffd83dbSDimitry Andric   // Generic 64-bit processor.
4095ffd83dbSDimitry Andric   { {"x86-64"}, CK_x86_64, ~0U, FeaturesX86_64 },
410af732203SDimitry Andric   { {"x86-64-v2"}, CK_x86_64_v2, ~0U, FeaturesX86_64_V2 },
411af732203SDimitry Andric   { {"x86-64-v3"}, CK_x86_64_v3, ~0U, FeaturesX86_64_V3 },
412af732203SDimitry Andric   { {"x86-64-v4"}, CK_x86_64_v4, ~0U, FeaturesX86_64_V4 },
4135ffd83dbSDimitry Andric   // Geode processors.
4145ffd83dbSDimitry Andric   { {"geode"}, CK_Geode, ~0U, FeaturesGeode },
4155ffd83dbSDimitry Andric };
4165ffd83dbSDimitry Andric 
417af732203SDimitry Andric constexpr const char *NoTuneList[] = {"x86-64-v2", "x86-64-v3", "x86-64-v4"};
418af732203SDimitry Andric 
parseArchX86(StringRef CPU,bool Only64Bit)4195ffd83dbSDimitry Andric X86::CPUKind llvm::X86::parseArchX86(StringRef CPU, bool Only64Bit) {
4205ffd83dbSDimitry Andric   for (const auto &P : Processors)
4215ffd83dbSDimitry Andric     if (P.Name == CPU && (P.Features[FEATURE_64BIT] || !Only64Bit))
4225ffd83dbSDimitry Andric       return P.Kind;
4235ffd83dbSDimitry Andric 
4245ffd83dbSDimitry Andric   return CK_None;
4255ffd83dbSDimitry Andric }
4265ffd83dbSDimitry Andric 
parseTuneCPU(StringRef CPU,bool Only64Bit)427af732203SDimitry Andric X86::CPUKind llvm::X86::parseTuneCPU(StringRef CPU, bool Only64Bit) {
428af732203SDimitry Andric   if (llvm::is_contained(NoTuneList, CPU))
429af732203SDimitry Andric     return CK_None;
430af732203SDimitry Andric   return parseArchX86(CPU, Only64Bit);
431af732203SDimitry Andric }
432af732203SDimitry Andric 
fillValidCPUArchList(SmallVectorImpl<StringRef> & Values,bool Only64Bit)4335ffd83dbSDimitry Andric void llvm::X86::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
4345ffd83dbSDimitry Andric                                      bool Only64Bit) {
4355ffd83dbSDimitry Andric   for (const auto &P : Processors)
4365ffd83dbSDimitry Andric     if (!P.Name.empty() && (P.Features[FEATURE_64BIT] || !Only64Bit))
4375ffd83dbSDimitry Andric       Values.emplace_back(P.Name);
4385ffd83dbSDimitry Andric }
4395ffd83dbSDimitry Andric 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values,bool Only64Bit)440af732203SDimitry Andric void llvm::X86::fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values,
441af732203SDimitry Andric                                      bool Only64Bit) {
442af732203SDimitry Andric   for (const ProcInfo &P : Processors)
443af732203SDimitry Andric     if (!P.Name.empty() && (P.Features[FEATURE_64BIT] || !Only64Bit) &&
444af732203SDimitry Andric         !llvm::is_contained(NoTuneList, P.Name))
445af732203SDimitry Andric       Values.emplace_back(P.Name);
446af732203SDimitry Andric }
447af732203SDimitry Andric 
getKeyFeature(X86::CPUKind Kind)4485ffd83dbSDimitry Andric ProcessorFeatures llvm::X86::getKeyFeature(X86::CPUKind Kind) {
4495ffd83dbSDimitry Andric   // FIXME: Can we avoid a linear search here? The table might be sorted by
4505ffd83dbSDimitry Andric   // CPUKind so we could binary search?
4515ffd83dbSDimitry Andric   for (const auto &P : Processors) {
4525ffd83dbSDimitry Andric     if (P.Kind == Kind) {
4535ffd83dbSDimitry Andric       assert(P.KeyFeature != ~0U && "Processor does not have a key feature.");
4545ffd83dbSDimitry Andric       return static_cast<ProcessorFeatures>(P.KeyFeature);
4555ffd83dbSDimitry Andric     }
4565ffd83dbSDimitry Andric   }
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric   llvm_unreachable("Unable to find CPU kind!");
4595ffd83dbSDimitry Andric }
4605ffd83dbSDimitry Andric 
4615ffd83dbSDimitry Andric // Features with no dependencies.
462af732203SDimitry Andric constexpr FeatureBitset ImpliedFeatures64BIT = {};
463af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesADX = {};
464af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesBMI = {};
465af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesBMI2 = {};
466af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCLDEMOTE = {};
467af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCLFLUSHOPT = {};
468af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCLWB = {};
469af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCLZERO = {};
470af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCMOV = {};
471af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCMPXCHG16B = {};
472af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesCMPXCHG8B = {};
473af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesENQCMD = {};
474af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesFSGSBASE = {};
475af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesFXSR = {};
476af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesINVPCID = {};
477af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesLWP = {};
478af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesLZCNT = {};
479af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesMWAITX = {};
480af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesMOVBE = {};
481af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesMOVDIR64B = {};
482af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesMOVDIRI = {};
483af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPCONFIG = {};
484af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPOPCNT = {};
485af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPKU = {};
486af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPREFETCHWT1 = {};
487af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPRFCHW = {};
488af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPTWRITE = {};
489af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRDPID = {};
490af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRDRND = {};
491af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRDSEED = {};
492af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRTM = {};
493af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSAHF = {};
494af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSERIALIZE = {};
495af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSGX = {};
496af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSHSTK = {};
497af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesTBM = {};
498af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesTSXLDTRK = {};
499af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesUINTR = {};
500af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesWAITPKG = {};
501af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesWBNOINVD = {};
502af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesVZEROUPPER = {};
503af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesX87 = {};
504af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesXSAVE = {};
5055ffd83dbSDimitry Andric 
5065ffd83dbSDimitry Andric // Not really CPU features, but need to be in the table because clang uses
5075ffd83dbSDimitry Andric // target features to communicate them to the backend.
508af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRETPOLINE_EXTERNAL_THUNK = {};
509af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRETPOLINE_INDIRECT_BRANCHES = {};
510af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesRETPOLINE_INDIRECT_CALLS = {};
511af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesLVI_CFI = {};
512af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesLVI_LOAD_HARDENING = {};
5135ffd83dbSDimitry Andric 
5145ffd83dbSDimitry Andric // XSAVE features are dependent on basic XSAVE.
515af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesXSAVEC = FeatureXSAVE;
516af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesXSAVEOPT = FeatureXSAVE;
517af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesXSAVES = FeatureXSAVE;
5185ffd83dbSDimitry Andric 
5195ffd83dbSDimitry Andric // MMX->3DNOW->3DNOWA chain.
520af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesMMX = {};
521af732203SDimitry Andric constexpr FeatureBitset ImpliedFeatures3DNOW = FeatureMMX;
522af732203SDimitry Andric constexpr FeatureBitset ImpliedFeatures3DNOWA = Feature3DNOW;
5235ffd83dbSDimitry Andric 
5245ffd83dbSDimitry Andric // SSE/AVX/AVX512F chain.
525af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE = {};
526af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE2 = FeatureSSE;
527af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE3 = FeatureSSE2;
528af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSSE3 = FeatureSSE3;
529af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE4_1 = FeatureSSSE3;
530af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE4_2 = FeatureSSE4_1;
531af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX = FeatureSSE4_2;
532af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX2 = FeatureAVX;
533af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512F =
5345ffd83dbSDimitry Andric     FeatureAVX2 | FeatureF16C | FeatureFMA;
5355ffd83dbSDimitry Andric 
5365ffd83dbSDimitry Andric // Vector extensions that build on SSE or AVX.
537af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAES = FeatureSSE2;
538af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesF16C = FeatureAVX;
539af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesFMA = FeatureAVX;
540af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesGFNI = FeatureSSE2;
541af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesPCLMUL = FeatureSSE2;
542af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSHA = FeatureSSE2;
543af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesVAES = FeatureAES | FeatureAVX;
544af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesVPCLMULQDQ = FeatureAVX | FeaturePCLMUL;
5455ffd83dbSDimitry Andric 
5465ffd83dbSDimitry Andric // AVX512 features.
547af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512CD = FeatureAVX512F;
548af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512BW = FeatureAVX512F;
549af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512DQ = FeatureAVX512F;
550af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512ER = FeatureAVX512F;
551af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512PF = FeatureAVX512F;
552af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VL = FeatureAVX512F;
5535ffd83dbSDimitry Andric 
554af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512BF16 = FeatureAVX512BW;
555af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512BITALG = FeatureAVX512BW;
556af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512IFMA = FeatureAVX512F;
557af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VNNI = FeatureAVX512F;
558af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VPOPCNTDQ = FeatureAVX512F;
559af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VBMI = FeatureAVX512BW;
560af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VBMI2 = FeatureAVX512BW;
561af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX512VP2INTERSECT = FeatureAVX512F;
5625ffd83dbSDimitry Andric 
5635ffd83dbSDimitry Andric // FIXME: These two aren't really implemented and just exist in the feature
5645ffd83dbSDimitry Andric // list for __builtin_cpu_supports. So omit their dependencies.
565af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX5124FMAPS = {};
566af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVX5124VNNIW = {};
5675ffd83dbSDimitry Andric 
5685ffd83dbSDimitry Andric // SSE4_A->FMA4->XOP chain.
569af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesSSE4_A = FeatureSSE3;
570af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesFMA4 = FeatureAVX | FeatureSSE4_A;
571af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesXOP = FeatureFMA4;
5725ffd83dbSDimitry Andric 
5735ffd83dbSDimitry Andric // AMX Features
574af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAMX_TILE = {};
575af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAMX_BF16 = FeatureAMX_TILE;
576af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAMX_INT8 = FeatureAMX_TILE;
577af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesHRESET = {};
5785ffd83dbSDimitry Andric 
579af732203SDimitry Andric // Key Locker Features
580af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesKL = FeatureSSE2;
581af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesWIDEKL = FeatureKL;
582af732203SDimitry Andric 
583af732203SDimitry Andric // AVXVNNI Features
584af732203SDimitry Andric constexpr FeatureBitset ImpliedFeaturesAVXVNNI = FeatureAVX2;
585af732203SDimitry Andric 
586af732203SDimitry Andric constexpr FeatureInfo FeatureInfos[X86::CPU_FEATURE_MAX] = {
5875ffd83dbSDimitry Andric #define X86_FEATURE(ENUM, STR) {{STR}, ImpliedFeatures##ENUM},
5885ffd83dbSDimitry Andric #include "llvm/Support/X86TargetParser.def"
5895ffd83dbSDimitry Andric };
5905ffd83dbSDimitry Andric 
getFeaturesForCPU(StringRef CPU,SmallVectorImpl<StringRef> & EnabledFeatures)5915ffd83dbSDimitry Andric void llvm::X86::getFeaturesForCPU(StringRef CPU,
5925ffd83dbSDimitry Andric                                   SmallVectorImpl<StringRef> &EnabledFeatures) {
5935ffd83dbSDimitry Andric   auto I = llvm::find_if(Processors,
5945ffd83dbSDimitry Andric                          [&](const ProcInfo &P) { return P.Name == CPU; });
5955ffd83dbSDimitry Andric   assert(I != std::end(Processors) && "Processor not found!");
5965ffd83dbSDimitry Andric 
5975ffd83dbSDimitry Andric   FeatureBitset Bits = I->Features;
5985ffd83dbSDimitry Andric 
5995ffd83dbSDimitry Andric   // Remove the 64-bit feature which we only use to validate if a CPU can
6005ffd83dbSDimitry Andric   // be used with 64-bit mode.
6015ffd83dbSDimitry Andric   Bits &= ~Feature64BIT;
6025ffd83dbSDimitry Andric 
6035ffd83dbSDimitry Andric   // Add the string version of all set bits.
604af732203SDimitry Andric   for (unsigned i = 0; i != CPU_FEATURE_MAX; ++i)
605af732203SDimitry Andric     if (Bits[i] && !FeatureInfos[i].Name.empty())
606af732203SDimitry Andric       EnabledFeatures.push_back(FeatureInfos[i].Name);
6075ffd83dbSDimitry Andric }
6085ffd83dbSDimitry Andric 
6095ffd83dbSDimitry Andric // For each feature that is (transitively) implied by this feature, set it.
getImpliedEnabledFeatures(FeatureBitset & Bits,const FeatureBitset & Implies)6105ffd83dbSDimitry Andric static void getImpliedEnabledFeatures(FeatureBitset &Bits,
6115ffd83dbSDimitry Andric                                       const FeatureBitset &Implies) {
61275b4d546SDimitry Andric   // Fast path: Implies is often empty.
61375b4d546SDimitry Andric   if (!Implies.any())
61475b4d546SDimitry Andric     return;
61575b4d546SDimitry Andric   FeatureBitset Prev;
6165ffd83dbSDimitry Andric   Bits |= Implies;
61775b4d546SDimitry Andric   do {
61875b4d546SDimitry Andric     Prev = Bits;
61975b4d546SDimitry Andric     for (unsigned i = CPU_FEATURE_MAX; i;)
62075b4d546SDimitry Andric       if (Bits[--i])
62175b4d546SDimitry Andric         Bits |= FeatureInfos[i].ImpliedFeatures;
62275b4d546SDimitry Andric   } while (Prev != Bits);
6235ffd83dbSDimitry Andric }
6245ffd83dbSDimitry Andric 
6255ffd83dbSDimitry Andric /// Create bit vector of features that are implied disabled if the feature
6265ffd83dbSDimitry Andric /// passed in Value is disabled.
getImpliedDisabledFeatures(FeatureBitset & Bits,unsigned Value)6275ffd83dbSDimitry Andric static void getImpliedDisabledFeatures(FeatureBitset &Bits, unsigned Value) {
6285ffd83dbSDimitry Andric   // Check all features looking for any dependent on this feature. If we find
6295ffd83dbSDimitry Andric   // one, mark it and recursively find any feature that depend on it.
63075b4d546SDimitry Andric   FeatureBitset Prev;
63175b4d546SDimitry Andric   Bits.set(Value);
63275b4d546SDimitry Andric   do {
63375b4d546SDimitry Andric     Prev = Bits;
63475b4d546SDimitry Andric     for (unsigned i = 0; i != CPU_FEATURE_MAX; ++i)
63575b4d546SDimitry Andric       if ((FeatureInfos[i].ImpliedFeatures & Bits).any())
6365ffd83dbSDimitry Andric         Bits.set(i);
63775b4d546SDimitry Andric   } while (Prev != Bits);
6385ffd83dbSDimitry Andric }
6395ffd83dbSDimitry Andric 
updateImpliedFeatures(StringRef Feature,bool Enabled,StringMap<bool> & Features)640af732203SDimitry Andric void llvm::X86::updateImpliedFeatures(
6415ffd83dbSDimitry Andric     StringRef Feature, bool Enabled,
642af732203SDimitry Andric     StringMap<bool> &Features) {
6435ffd83dbSDimitry Andric   auto I = llvm::find_if(
6445ffd83dbSDimitry Andric       FeatureInfos, [&](const FeatureInfo &FI) { return FI.Name == Feature; });
6455ffd83dbSDimitry Andric   if (I == std::end(FeatureInfos)) {
6465ffd83dbSDimitry Andric     // FIXME: This shouldn't happen, but may not have all features in the table
6475ffd83dbSDimitry Andric     // yet.
6485ffd83dbSDimitry Andric     return;
6495ffd83dbSDimitry Andric   }
6505ffd83dbSDimitry Andric 
6515ffd83dbSDimitry Andric   FeatureBitset ImpliedBits;
6525ffd83dbSDimitry Andric   if (Enabled)
6535ffd83dbSDimitry Andric     getImpliedEnabledFeatures(ImpliedBits, I->ImpliedFeatures);
6545ffd83dbSDimitry Andric   else
6555ffd83dbSDimitry Andric     getImpliedDisabledFeatures(ImpliedBits,
6565ffd83dbSDimitry Andric                                std::distance(std::begin(FeatureInfos), I));
6575ffd83dbSDimitry Andric 
658af732203SDimitry Andric   // Update the map entry for all implied features.
659af732203SDimitry Andric   for (unsigned i = 0; i != CPU_FEATURE_MAX; ++i)
660af732203SDimitry Andric     if (ImpliedBits[i] && !FeatureInfos[i].Name.empty())
661af732203SDimitry Andric       Features[FeatureInfos[i].Name] = Enabled;
6625ffd83dbSDimitry Andric }
663