#define LLVM_MC_SUBTARGETFEATURE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
#include <array>
#include <bitset>
#include <initializer_list>
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> {
+/// 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];
+ }
+
public:
- // Cannot inherit constructors because it's not supported by VC++..
FeatureBitset() = default;
-
- FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
-
- FeatureBitset(std::initializer_list<unsigned> Init) {
+ 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) {
+ Bits[I / 64] |= uint64_t(1) << (I % 64);
+ return *this;
+ }
+
+ constexpr FeatureBitset &reset(unsigned I) {
+ Bits[I / 64] &= ~(uint64_t(1) << (I % 64));
+ return *this;
+ }
+
+ constexpr FeatureBitset &flip(unsigned I) {
+ Bits[I / 64] ^= uint64_t(1) << (I % 64);
+ 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);
};
/// 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; }
};
//===----------------------------------------------------------------------===//
uint16_t Encoding;
FeatureBitset FeaturesRequired;
- SysAlias (const char *N, uint16_t E) : Name(N), Encoding(E) {};
- SysAlias (const char *N, uint16_t E, FeatureBitset F) :
- Name(N), Encoding(E), FeaturesRequired(F) {};
+ constexpr SysAlias(const char *N, uint16_t E) : Name(N), Encoding(E) {}
+ constexpr SysAlias(const char *N, uint16_t E, FeatureBitset F)
+ : Name(N), Encoding(E), FeaturesRequired(F) {}
bool haveFeatures(FeatureBitset ActiveFeatures) const {
return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
struct SysAliasReg : SysAlias {
bool NeedsReg;
- SysAliasReg(const char *N, uint16_t E, bool R) : SysAlias(N, E), NeedsReg(R) {};
- SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F) : SysAlias(N, E, F),
- NeedsReg(R) {};
+ constexpr SysAliasReg(const char *N, uint16_t E, bool R)
+ : SysAlias(N, E), NeedsReg(R) {}
+ constexpr SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F)
+ : SysAlias(N, E, F), NeedsReg(R) {}
};
namespace AArch64AT{
FeatureBitset Features = getFeatureBits();
if (HexagonDisableDuplex)
- setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
+ setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
setFeatureBits(Hexagon_MC::completeHVXFeatures(Features));
return *this;
}
static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
- uint64_t FB = STI->getFeatureBits().to_ullong();
- if (FB & (1ULL << F))
+ if (STI->getFeatureBits()[F])
STI->ToggleFeature(F);
}
static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
- uint64_t FB = STI->getFeatureBits().to_ullong();
- return (FB & (1ULL << F)) != 0;
+ return STI->getFeatureBits()[F];
}
namespace {
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
if (HexagonDisableDuplex) {
llvm::FeatureBitset Features = X->getFeatureBits();
- X->setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
+ X->setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
}
X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));
// CHECK-NEXT: computeAvailableModuleFeatures(const MyTargetSubtarget *Subtarget) const {
// CHECK-NEXT: PredicateBitset Features;
// CHECK-NEXT: if (Subtarget->hasA())
-// CHECK-NEXT: Features[Feature_HasABit] = 1;
+// CHECK-NEXT: Features.set(Feature_HasABit);
// CHECK-NEXT: if (Subtarget->hasB())
-// CHECK-NEXT: Features[Feature_HasBBit] = 1;
+// CHECK-NEXT: Features.set(Feature_HasBBit);
// CHECK-NEXT: return Features;
// CHECK-NEXT: }
// CHECK-NEXT: computeAvailableFunctionFeatures(const MyTargetSubtarget *Subtarget, const MachineFunction *MF) const {
// CHECK-NEXT: PredicateBitset Features;
// CHECK-NEXT: if (Subtarget->hasC())
-// CHECK-NEXT: Features[Feature_HasCBit] = 1;
+// CHECK-NEXT: Features.set(Feature_HasCBit);
// CHECK-NEXT: return Features;
// CHECK-NEXT: }
OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
}
OS << "};\n\n"
- << "const static FeatureBitset FeatureBitsets[] {\n"
+ << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
<< " {}, // AMFBS_None\n";
for (const auto &FeatureBitset : FeatureBitsets) {
if (FeatureBitset.empty())
o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
}
o << "};\n\n"
- << "const static FeatureBitset FeatureBitsets[] {\n"
- << " {}, // CEFBS_None\n";
+ << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
+ << " {}, // CEFBS_None\n";
for (const auto &FeatureBitset : FeatureBitsets) {
if (FeatureBitset.empty())
continue;
emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_IMPL").str(), OS);
// The primary data table contains all the fields defined for this map.
- OS << "const " << Table.CppTypeName << " " << Table.Name << "[] = {\n";
+ OS << "constexpr " << Table.CppTypeName << " " << Table.Name << "[] = {\n";
for (unsigned i = 0; i < Table.Entries.size(); ++i) {
Record *Entry = Table.Entries[i];
OS << " { ";
assert(!CondStr.empty() && "true predicate should have been filtered");
OS << " if (" << CondStr << ")\n";
- OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
+ OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
}
OS << " return Features;\n";
OS << "}\n\n";
} while (true);
OS << ")\n";
- OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
+ OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
}
OS << " return Features;\n";
OS << "}\n\n";