[PATCH] D82731: [X86] Move frontend CPU feature initialization to a look up table based implementation.

2020-06-30 Thread Craig Topper via Phabricator via cfe-commits
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.

2020-06-30 Thread Simon Pilgrim via Phabricator via cfe-commits
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.

2020-06-29 Thread Craig Topper via Phabricator via cfe-commits
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.

2020-06-29 Thread Craig Topper via Phabricator via cfe-commits
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.

2020-06-29 Thread Erich Keane via Phabricator via cfe-commits
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.

2020-06-29 Thread Craig Topper via Phabricator via cfe-commits
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