[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
This revision was automatically updated to reflect the committed changes. Closed by commit rG3537939cda86: [X86] Move frontend CPU feature initialization to a look up table based… (authored by craig.topper). Changed prior to commit: https://reviews.llvm.org/D82731?vs=274161&id=274586#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82731/new/ https://reviews.llvm.org/D82731 Files: clang/lib/Basic/Targets/X86.cpp clang/lib/CodeGen/CGBuiltin.cpp llvm/include/llvm/Support/X86TargetParser.def llvm/include/llvm/Support/X86TargetParser.h llvm/lib/Support/X86TargetParser.cpp Index: llvm/lib/Support/X86TargetParser.cpp === --- llvm/lib/Support/X86TargetParser.cpp +++ llvm/lib/Support/X86TargetParser.cpp @@ -19,134 +19,339 @@ namespace { +/// Container class for CPU features. +/// This is a constexpr reimplementation of a subset of std::bitset. It would be +/// nice to use std::bitset directly, but it doesn't support constant +/// initialization. +class FeatureBitset { + static constexpr unsigned NUM_FEATURE_WORDS = + (X86::CPU_FEATURE_MAX + 31) / 32; + + // This cannot be a std::array, operator[] is not constexpr until C++17. + uint32_t Bits[NUM_FEATURE_WORDS] = {}; + +public: + constexpr FeatureBitset() = default; + constexpr FeatureBitset(std::initializer_list Init) { +for (auto I : Init) + set(I); + } + + constexpr FeatureBitset &set(unsigned I) { +uint32_t NewBits = Bits[I / 32] | (uint32_t(1) << (I % 32)); +Bits[I / 32] = NewBits; +return *this; + } + + constexpr bool operator[](unsigned I) const { +uint32_t Mask = uint32_t(1) << (I % 32); +return (Bits[I / 32] & Mask) != 0; + } + + constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] & RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] | RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator~() const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = ~Bits[I]; +return Result; + } +}; + struct ProcInfo { StringLiteral Name; X86::CPUKind Kind; unsigned KeyFeature; - bool Is64Bit; + FeatureBitset Features; }; } // end anonymous namespace -#define PROC_64_BIT true -#define PROC_32_BIT false +#define X86_FEATURE(ENUM, STRING) \ + static constexpr FeatureBitset Feature##ENUM = {X86::FEATURE_##ENUM}; +#include "llvm/Support/X86TargetParser.def" + +// Pentium with MMX. +static constexpr FeatureBitset FeaturesPentiumMMX = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX; + +// Pentium 2 and 3. +static constexpr FeatureBitset FeaturesPentium2 = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | FeatureFXSR; +static constexpr FeatureBitset FeaturesPentium3 = FeaturesPentium2 | FeatureSSE; + +// Pentium 4 CPUs +static constexpr FeatureBitset FeaturesPentium4 = +FeaturesPentium3 | FeatureSSE2; +static constexpr FeatureBitset FeaturesPrescott = +FeaturesPentium4 | FeatureSSE3; +static constexpr FeatureBitset FeaturesNocona = +FeaturesPrescott | FeatureEM64T | FeatureCMPXCHG16B; + +// Basic 64-bit capable CPU. +static constexpr FeatureBitset FeaturesX86_64 = FeaturesPentium4 | FeatureEM64T; + +// Intel Core CPUs +static constexpr FeatureBitset FeaturesCore2 = +FeaturesNocona | FeatureSAHF | FeatureSSSE3; +static constexpr FeatureBitset FeaturesPenryn = FeaturesCore2 | FeatureSSE4_1; +static constexpr FeatureBitset FeaturesNehalem = +FeaturesPenryn | FeaturePOPCNT | FeatureSSE4_2; +static constexpr FeatureBitset FeaturesWestmere = +FeaturesNehalem | FeaturePCLMUL; +static constexpr FeatureBitset FeaturesSandyBridge = +FeaturesWestmere | FeatureAVX | FeatureXSAVE | FeatureXSAVEOPT; +static constexpr FeatureBitset FeaturesIvyBridge = +FeaturesSandyBridge | FeatureF16C | FeatureFSGSBASE | FeatureRDRND; +static constexpr FeatureBitset FeaturesHaswell = +FeaturesIvyBridge | FeatureAVX2 | FeatureBMI | FeatureBMI2 | FeatureFMA | +FeatureINVPCID | FeatureLZCNT | FeatureMOVBE; +static constexpr FeatureBitset FeaturesBroadwell = +FeaturesHaswell | FeatureADX | FeaturePRFCHW | FeatureRDSEED; + +// Intel Knights Landing and Knights Mill +// Knights Landing has feature parity with Broadwell. +static constexpr FeatureBitset FeaturesKNL = +FeaturesBroadwell | FeatureAES | FeatureAVX512F | FeatureAVX512CD | +FeatureAVX512ER | FeatureAVX512PF | FeaturePREFETCHWT1; +static constexpr FeatureBitset FeaturesKNM = +FeaturesKNL | FeatureAVX512VPOPCNTDQ; + +// Intel Skylake processors. +static con
[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
RKSimon added a comment. LGTM with a couple of minors Comment at: clang/test/Preprocessor/predefined-arch-macros.c:2835 // CHECK_ZNVER1_M32: #define __F16C__ 1 +// CHECK_ZNVER1_M32-NOT: #define __FMA4__ 1 // CHECK_ZNVER1_M32: #define __FMA__ 1 The additional znver -NOT checks should definitely be split out. Comment at: llvm/lib/Support/X86TargetParser.cpp:179 +static constexpr FeatureBitset FeaturesGeode = +FeaturesPentiumMMX | Feature3DNOW | Feature3DNOWA; + Maybe don't make this dependent on PentiumMMX? FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | Feature3DNOW | Feature3DNOWA Comment at: llvm/lib/Support/X86TargetParser.cpp:312 // K6 architecture processors. - { {"k6"}, CK_K6, ~0U, PROC_32_BIT }, - { {"k6-2"}, CK_K6_2, ~0U, PROC_32_BIT }, - { {"k6-3"}, CK_K6_3, ~0U, PROC_32_BIT }, + { {"k6"}, CK_K6, ~0U, FeaturesPentiumMMX }, + { {"k6-2"}, CK_K6_2, ~0U, FeaturesPentiumMMX | Feature3DNOW }, Maybe create a FeaturesK6 and build k6-2/3 off that? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82731/new/ https://reviews.llvm.org/D82731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
craig.topper added a comment. @RKSimon do you mind taking a look at this too? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82731/new/ https://reviews.llvm.org/D82731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
craig.topper updated this revision to Diff 274161. craig.topper added a comment. -Run clang-format. Some lines in the table are still slightly over 80 columns. -Fix the number of words in the FeatureBitset. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82731/new/ https://reviews.llvm.org/D82731 Files: clang/lib/Basic/Targets/X86.cpp clang/lib/CodeGen/CGBuiltin.cpp clang/test/Preprocessor/predefined-arch-macros.c llvm/include/llvm/Support/X86TargetParser.def llvm/include/llvm/Support/X86TargetParser.h llvm/lib/Support/X86TargetParser.cpp Index: llvm/lib/Support/X86TargetParser.cpp === --- llvm/lib/Support/X86TargetParser.cpp +++ llvm/lib/Support/X86TargetParser.cpp @@ -19,134 +19,335 @@ namespace { +/// Container class for CPU features. +/// This is a constexpr reimplementation of a subset of std::bitset. It would be +/// nice to use std::bitset directly, but it doesn't support constant +/// initialization. +class FeatureBitset { + static constexpr unsigned NUM_FEATURE_WORDS = + (X86::CPU_FEATURE_MAX + 31) / 32; + + // This cannot be a std::array, operator[] is not constexpr until C++17. + uint32_t Bits[NUM_FEATURE_WORDS] = {}; + +public: + constexpr FeatureBitset() = default; + constexpr FeatureBitset(std::initializer_list Init) { +for (auto I : Init) + set(I); + } + + constexpr FeatureBitset &set(unsigned I) { +uint32_t NewBits = Bits[I / 32] | (uint32_t(1) << (I % 32)); +Bits[I / 32] = NewBits; +return *this; + } + + constexpr bool operator[](unsigned I) const { +uint32_t Mask = uint32_t(1) << (I % 32); +return (Bits[I / 32] & Mask) != 0; + } + + constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] & RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] | RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator~() const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = ~Bits[I]; +return Result; + } +}; + struct ProcInfo { StringLiteral Name; X86::CPUKind Kind; unsigned KeyFeature; - bool Is64Bit; + FeatureBitset Features; }; } // end anonymous namespace -#define PROC_64_BIT true -#define PROC_32_BIT false +#define X86_FEATURE(ENUM, STRING) \ + static constexpr FeatureBitset Feature##ENUM = {X86::FEATURE_##ENUM}; +#include "llvm/Support/X86TargetParser.def" + +// Pentium with MMX. +static constexpr FeatureBitset FeaturesPentiumMMX = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX; + +// Pentium 2 and 3. +static constexpr FeatureBitset FeaturesPentium2 = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | FeatureFXSR; +static constexpr FeatureBitset FeaturesPentium3 = FeaturesPentium2 | FeatureSSE; + +// Pentium 4 CPUs +static constexpr FeatureBitset FeaturesPentium4 = +FeaturesPentium3 | FeatureSSE2; +static constexpr FeatureBitset FeaturesPrescott = +FeaturesPentium4 | FeatureSSE3; +static constexpr FeatureBitset FeaturesNocona = +FeaturesPrescott | FeatureEM64T | FeatureCMPXCHG16B; + +// Basic 64-bit capable CPU. +static constexpr FeatureBitset FeaturesX86_64 = FeaturesPentium4 | FeatureEM64T; + +// Intel Core CPUs +static constexpr FeatureBitset FeaturesCore2 = +FeaturesNocona | FeatureSAHF | FeatureSSSE3; +static constexpr FeatureBitset FeaturesPenryn = FeaturesCore2 | FeatureSSE4_1; +static constexpr FeatureBitset FeaturesNehalem = +FeaturesPenryn | FeaturePOPCNT | FeatureSSE4_2; +static constexpr FeatureBitset FeaturesWestmere = +FeaturesNehalem | FeaturePCLMUL; +static constexpr FeatureBitset FeaturesSandyBridge = +FeaturesWestmere | FeatureAVX | FeatureXSAVE | FeatureXSAVEOPT; +static constexpr FeatureBitset FeaturesIvyBridge = +FeaturesSandyBridge | FeatureF16C | FeatureFSGSBASE | FeatureRDRND; +static constexpr FeatureBitset FeaturesHaswell = +FeaturesIvyBridge | FeatureAVX2 | FeatureBMI | FeatureBMI2 | FeatureFMA | +FeatureINVPCID | FeatureLZCNT | FeatureMOVBE; +static constexpr FeatureBitset FeaturesBroadwell = +FeaturesHaswell | FeatureADX | FeaturePRFCHW | FeatureRDSEED; + +// Intel Knights Landing and Knights Mill +// Knights Landing has feature parity with Broadwell. +static constexpr FeatureBitset FeaturesKNL = +FeaturesBroadwell | FeatureAES | FeatureAVX512F | FeatureAVX512CD | +FeatureAVX512ER | FeatureAVX512PF | FeaturePREFETCHWT1; +static constexpr FeatureBitset FeaturesKNM = +FeaturesKNL | FeatureAVX512VPOPCNTDQ; + +// Intel Skylake processors. +static constexpr FeatureBitset FeaturesSkyl
[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
erichkeane accepted this revision. erichkeane added a comment. This revision is now accepted and ready to land. A bunch of clang-format, plus 1 odd looking equation, otherwise this like good. Comment at: llvm/lib/Support/X86TargetParser.cpp:27 +class FeatureBitset { + static constexpr unsigned NUM_FEATURE_WORDS = X86::CPU_FEATURE_MAX + 31 / 32; + Why is this CPU_FEATURE_MAX + 0? Are you missing parens? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82731/new/ https://reviews.llvm.org/D82731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.
craig.topper created this revision. craig.topper added reviewers: RKSimon, spatel, LuoYuanke, LiuChen3, echristo, FreddyYe. Herald added subscribers: jfb, hiraditya. Herald added projects: clang, LLVM. craig.topper added a reviewer: erichkeane. This replaces the switch statement implementation in the clang's X86.cpp with a lookup table X86TargetParser.cpp. I've used constexpr and copy of the FeatureBitset from SubtargetFeature.h to store the features in a lookup table. After the lookup the bitset is translated into strings for use by the rest of the frontend code. I had to modify the implementation of the FeatureBitset to avoid bugs in libgcc's constexpr handling. It seems to not like the same array entry to be used on the left side and right hand side of an assignment or &= or |=. I've also used uint32_t instead of uint64_t and sized based on the X86::CPU_FEATURE_MAX. I've initialized the features for different CPUs outside of the table so that they can be inherited from to express inheritance in an adhoc way. This was one of the big limitations of the switch where had resorted to labels and gotos. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D82731 Files: clang/lib/Basic/Targets/X86.cpp clang/lib/CodeGen/CGBuiltin.cpp clang/test/Preprocessor/predefined-arch-macros.c llvm/include/llvm/Support/X86TargetParser.def llvm/include/llvm/Support/X86TargetParser.h llvm/lib/Support/X86TargetParser.cpp Index: llvm/lib/Support/X86TargetParser.cpp === --- llvm/lib/Support/X86TargetParser.cpp +++ llvm/lib/Support/X86TargetParser.cpp @@ -19,134 +19,333 @@ namespace { +/// Container class for CPU features. +/// This is a constexpr reimplementation of a subset of std::bitset. It would be +/// nice to use std::bitset directly, but it doesn't support constant +/// initialization. +class FeatureBitset { + static constexpr unsigned NUM_FEATURE_WORDS = X86::CPU_FEATURE_MAX + 31 / 32; + + // This cannot be a std::array, operator[] is not constexpr until C++17. + uint32_t Bits[NUM_FEATURE_WORDS] = {}; + +public: + constexpr FeatureBitset() = default; + constexpr FeatureBitset(std::initializer_list Init) { +for (auto I : Init) + set(I); + } + + constexpr FeatureBitset &set(unsigned I) { +uint32_t NewBits = Bits[I / 32] | (uint32_t(1) << (I % 32)); +Bits[I / 32] = NewBits; +return *this; + } + + constexpr bool operator[](unsigned I) const { +uint32_t Mask = uint32_t(1) << (I % 32); +return (Bits[I / 32] & Mask) != 0; + } + + constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] & RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = Bits[I] | RHS.Bits[I]; +return Result; + } + + constexpr FeatureBitset operator~() const { +FeatureBitset Result; +for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) + Result.Bits[I] = ~Bits[I]; +return Result; + } +}; + struct ProcInfo { StringLiteral Name; X86::CPUKind Kind; unsigned KeyFeature; - bool Is64Bit; + FeatureBitset Features; }; } // end anonymous namespace -#define PROC_64_BIT true -#define PROC_32_BIT false +#define X86_FEATURE(ENUM, STRING) \ + static constexpr FeatureBitset Feature##ENUM = {X86::FEATURE_##ENUM}; +#include "llvm/Support/X86TargetParser.def" + +// Pentium with MMX. +static constexpr FeatureBitset FeaturesPentiumMMX = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX; + +// Pentium 2 and 3. +static constexpr FeatureBitset FeaturesPentium2 = +FeatureX87 | FeatureCMPXCHG8B | FeatureMMX | FeatureFXSR; +static constexpr FeatureBitset FeaturesPentium3 = +FeaturesPentium2 | FeatureSSE; + +// Pentium 4 CPUs +static constexpr FeatureBitset FeaturesPentium4 = +FeaturesPentium3 | FeatureSSE2; +static constexpr FeatureBitset FeaturesPrescott = +FeaturesPentium4 | FeatureSSE3; +static constexpr FeatureBitset FeaturesNocona = +FeaturesPrescott | FeatureEM64T | FeatureCMPXCHG16B; + +// Basic 64-bit capable CPU. +static constexpr FeatureBitset FeaturesX86_64 = +FeaturesPentium4 | FeatureEM64T; + +// Intel Core CPUs +static constexpr FeatureBitset FeaturesCore2 = +FeaturesNocona | FeatureSAHF | FeatureSSSE3; +static constexpr FeatureBitset FeaturesPenryn = FeaturesCore2 | FeatureSSE4_1; +static constexpr FeatureBitset FeaturesNehalem = +FeaturesPenryn | FeaturePOPCNT | FeatureSSE4_2; +static constexpr FeatureBitset FeaturesWestmere = +FeaturesNehalem | FeaturePCLMUL; +static constexpr FeatureBitset FeaturesSandyBridge = +FeaturesWestmere | FeatureAVX | FeatureXSAVE | FeatureXSAVEOPT; +static constexpr Fe