summaryrefslogtreecommitdiff
path: root/include/llvm/MC/SubtargetFeature.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/MC/SubtargetFeature.h')
-rw-r--r--include/llvm/MC/SubtargetFeature.h139
1 files changed, 116 insertions, 23 deletions
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index fc9565ceafad..defbc3c64720 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -18,6 +18,7 @@
#define LLVM_MC_SUBTARGETFEATURE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
#include <array>
#include <bitset>
#include <initializer_list>
@@ -33,20 +34,123 @@ const unsigned MAX_SUBTARGET_WORDS = 3;
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
/// Container class for subtarget features.
-/// This is convenient because std::bitset does not have a constructor
-/// with an initializer list of set bits.
-class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
-public:
- // Cannot inherit constructors because it's not supported by VC++..
- FeatureBitset() = default;
-
- FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
+/// 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_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
+ "Should be a multiple of 64!");
+ // This cannot be a std::array, operator[] is not constexpr until C++17.
+ uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
+
+protected:
+ constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) {
+ for (unsigned I = 0; I != B.size(); ++I)
+ Bits[I] = B[I];
+ }
- FeatureBitset(std::initializer_list<unsigned> Init) {
+public:
+ constexpr FeatureBitset() = default;
+ constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
for (auto I : Init)
set(I);
}
+ FeatureBitset &set() {
+ std::fill(std::begin(Bits), std::end(Bits), -1ULL);
+ return *this;
+ }
+
+ constexpr FeatureBitset &set(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr FeatureBitset &reset(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr FeatureBitset &flip(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr bool operator[](unsigned I) const {
+ uint64_t Mask = uint64_t(1) << (I % 64);
+ return (Bits[I / 64] & Mask) != 0;
+ }
+
+ constexpr bool test(unsigned I) const { return (*this)[I]; }
+
+ constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
+
+ bool any() const {
+ return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
+ }
+ bool none() const { return !any(); }
+ size_t count() const {
+ size_t Count = 0;
+ for (auto B : Bits)
+ Count += countPopulation(B);
+ return Count;
+ }
+
+ constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] ^= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result ^= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] &= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result &= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] |= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result |= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset operator~() const {
+ FeatureBitset Result = *this;
+ for (auto &B : Result.Bits)
+ B = ~B;
+ return Result;
+ }
+
+ bool operator==(const FeatureBitset &RHS) const {
+ return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
+ }
+
+ bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
+
bool operator < (const FeatureBitset &Other) const {
for (unsigned I = 0, E = size(); I != E; ++I) {
bool LHS = test(I), RHS = Other.test(I);
@@ -58,23 +162,12 @@ public:
};
/// Class used to store the subtarget bits in the tables created by tablegen.
-/// The std::initializer_list constructor of FeatureBitset can't be done at
-/// compile time and requires a static constructor to run at startup.
-class FeatureBitArray {
- std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits;
-
+class FeatureBitArray : public FeatureBitset {
public:
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
- : Bits(B) {}
-
- FeatureBitset getAsBitset() const {
- FeatureBitset Result;
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i)
- Result |= FeatureBitset(Bits[i]) << (64 * i);
+ : FeatureBitset(B) {}
- return Result;
- }
+ const FeatureBitset &getAsBitset() const { return *this; }
};
//===----------------------------------------------------------------------===//