forked from OSchip/llvm-project
Use a bit of relaxed constexpr to make FeatureBitset costant intializable
This requires std::intializer_list to be a literal type, which it is starting with C++14. The downside is that std::bitset is still not constexpr-friendly so this change contains a re-implementation of most of it. Shrinks clang by ~60k. llvm-svn: 369847
This commit is contained in:
parent
19651b68d9
commit
16b322914a
|
@ -18,6 +18,7 @@
|
||||||
#define LLVM_MC_SUBTARGETFEATURE_H
|
#define LLVM_MC_SUBTARGETFEATURE_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
@ -33,20 +34,117 @@ const unsigned MAX_SUBTARGET_WORDS = 3;
|
||||||
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
|
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
|
||||||
|
|
||||||
/// Container class for subtarget features.
|
/// Container class for subtarget features.
|
||||||
/// This is convenient because std::bitset does not have a constructor
|
/// This is a constexpr reimplementation of a subset of std::bitset. It would be
|
||||||
/// with an initializer list of set bits.
|
/// nice to use std::bitset directly, but it doesn't support constant
|
||||||
class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
|
/// 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:
|
public:
|
||||||
// Cannot inherit constructors because it's not supported by VC++..
|
|
||||||
FeatureBitset() = default;
|
FeatureBitset() = default;
|
||||||
|
constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
|
||||||
FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
|
|
||||||
|
|
||||||
FeatureBitset(std::initializer_list<unsigned> Init) {
|
|
||||||
for (auto I : Init)
|
for (auto I : Init)
|
||||||
set(I);
|
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 {
|
bool operator < (const FeatureBitset &Other) const {
|
||||||
for (unsigned I = 0, E = size(); I != E; ++I) {
|
for (unsigned I = 0, E = size(); I != E; ++I) {
|
||||||
bool LHS = test(I), RHS = Other.test(I);
|
bool LHS = test(I), RHS = Other.test(I);
|
||||||
|
@ -58,23 +156,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Class used to store the subtarget bits in the tables created by tablegen.
|
/// 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
|
class FeatureBitArray : public FeatureBitset {
|
||||||
/// compile time and requires a static constructor to run at startup.
|
|
||||||
class FeatureBitArray {
|
|
||||||
std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
|
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
|
||||||
: Bits(B) {}
|
: FeatureBitset(B) {}
|
||||||
|
|
||||||
FeatureBitset getAsBitset() const {
|
const FeatureBitset &getAsBitset() const { return *this; }
|
||||||
FeatureBitset Result;
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = Bits.size(); i != e; ++i)
|
|
||||||
Result |= FeatureBitset(Bits[i]) << (64 * i);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -313,9 +313,9 @@ struct SysAlias {
|
||||||
uint16_t Encoding;
|
uint16_t Encoding;
|
||||||
FeatureBitset FeaturesRequired;
|
FeatureBitset FeaturesRequired;
|
||||||
|
|
||||||
SysAlias (const char *N, uint16_t E) : Name(N), Encoding(E) {};
|
constexpr SysAlias(const char *N, uint16_t E) : Name(N), Encoding(E) {}
|
||||||
SysAlias (const char *N, uint16_t E, FeatureBitset F) :
|
constexpr SysAlias(const char *N, uint16_t E, FeatureBitset F)
|
||||||
Name(N), Encoding(E), FeaturesRequired(F) {};
|
: Name(N), Encoding(E), FeaturesRequired(F) {}
|
||||||
|
|
||||||
bool haveFeatures(FeatureBitset ActiveFeatures) const {
|
bool haveFeatures(FeatureBitset ActiveFeatures) const {
|
||||||
return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
|
return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
|
||||||
|
@ -326,9 +326,10 @@ struct SysAlias {
|
||||||
|
|
||||||
struct SysAliasReg : SysAlias {
|
struct SysAliasReg : SysAlias {
|
||||||
bool NeedsReg;
|
bool NeedsReg;
|
||||||
SysAliasReg(const char *N, uint16_t E, bool R) : SysAlias(N, E), NeedsReg(R) {};
|
constexpr SysAliasReg(const char *N, uint16_t E, bool R)
|
||||||
SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F) : SysAlias(N, E, F),
|
: SysAlias(N, E), NeedsReg(R) {}
|
||||||
NeedsReg(R) {};
|
constexpr SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F)
|
||||||
|
: SysAlias(N, E, F), NeedsReg(R) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace AArch64AT{
|
namespace AArch64AT{
|
||||||
|
|
|
@ -119,7 +119,7 @@ HexagonSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
|
||||||
|
|
||||||
FeatureBitset Features = getFeatureBits();
|
FeatureBitset Features = getFeatureBits();
|
||||||
if (HexagonDisableDuplex)
|
if (HexagonDisableDuplex)
|
||||||
setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
|
setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
|
||||||
setFeatureBits(Hexagon_MC::completeHVXFeatures(Features));
|
setFeatureBits(Hexagon_MC::completeHVXFeatures(Features));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -264,14 +264,12 @@ createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
|
static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
|
||||||
uint64_t FB = STI->getFeatureBits().to_ullong();
|
if (STI->getFeatureBits()[F])
|
||||||
if (FB & (1ULL << F))
|
|
||||||
STI->ToggleFeature(F);
|
STI->ToggleFeature(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
|
static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
|
||||||
uint64_t FB = STI->getFeatureBits().to_ullong();
|
return STI->getFeatureBits()[F];
|
||||||
return (FB & (1ULL << F)) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -398,7 +396,7 @@ MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
|
||||||
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
|
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
|
||||||
if (HexagonDisableDuplex) {
|
if (HexagonDisableDuplex) {
|
||||||
llvm::FeatureBitset Features = X->getFeatureBits();
|
llvm::FeatureBitset Features = X->getFeatureBits();
|
||||||
X->setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
|
X->setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
|
||||||
}
|
}
|
||||||
|
|
||||||
X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));
|
X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));
|
||||||
|
|
|
@ -96,9 +96,9 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||||
// CHECK-NEXT: computeAvailableModuleFeatures(const MyTargetSubtarget *Subtarget) const {
|
// CHECK-NEXT: computeAvailableModuleFeatures(const MyTargetSubtarget *Subtarget) const {
|
||||||
// CHECK-NEXT: PredicateBitset Features;
|
// CHECK-NEXT: PredicateBitset Features;
|
||||||
// CHECK-NEXT: if (Subtarget->hasA())
|
// CHECK-NEXT: if (Subtarget->hasA())
|
||||||
// CHECK-NEXT: Features[Feature_HasABit] = 1;
|
// CHECK-NEXT: Features.set(Feature_HasABit);
|
||||||
// CHECK-NEXT: if (Subtarget->hasB())
|
// CHECK-NEXT: if (Subtarget->hasB())
|
||||||
// CHECK-NEXT: Features[Feature_HasBBit] = 1;
|
// CHECK-NEXT: Features.set(Feature_HasBBit);
|
||||||
// CHECK-NEXT: return Features;
|
// CHECK-NEXT: return Features;
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||||
// CHECK-NEXT: computeAvailableFunctionFeatures(const MyTargetSubtarget *Subtarget, const MachineFunction *MF) const {
|
// CHECK-NEXT: computeAvailableFunctionFeatures(const MyTargetSubtarget *Subtarget, const MachineFunction *MF) const {
|
||||||
// CHECK-NEXT: PredicateBitset Features;
|
// CHECK-NEXT: PredicateBitset Features;
|
||||||
// CHECK-NEXT: if (Subtarget->hasC())
|
// CHECK-NEXT: if (Subtarget->hasC())
|
||||||
// CHECK-NEXT: Features[Feature_HasCBit] = 1;
|
// CHECK-NEXT: Features.set(Feature_HasCBit);
|
||||||
// CHECK-NEXT: return Features;
|
// CHECK-NEXT: return Features;
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
|
|
|
@ -3366,7 +3366,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||||
OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
|
OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
|
||||||
}
|
}
|
||||||
OS << "};\n\n"
|
OS << "};\n\n"
|
||||||
<< "const static FeatureBitset FeatureBitsets[] {\n"
|
<< "static constexpr FeatureBitset FeatureBitsets[] = {\n"
|
||||||
<< " {}, // AMFBS_None\n";
|
<< " {}, // AMFBS_None\n";
|
||||||
for (const auto &FeatureBitset : FeatureBitsets) {
|
for (const auto &FeatureBitset : FeatureBitsets) {
|
||||||
if (FeatureBitset.empty())
|
if (FeatureBitset.empty())
|
||||||
|
|
|
@ -385,8 +385,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
|
||||||
o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
|
o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
|
||||||
}
|
}
|
||||||
o << "};\n\n"
|
o << "};\n\n"
|
||||||
<< "const static FeatureBitset FeatureBitsets[] {\n"
|
<< "static constexpr FeatureBitset FeatureBitsets[] = {\n"
|
||||||
<< " {}, // CEFBS_None\n";
|
<< " {}, // CEFBS_None\n";
|
||||||
for (const auto &FeatureBitset : FeatureBitsets) {
|
for (const auto &FeatureBitset : FeatureBitsets) {
|
||||||
if (FeatureBitset.empty())
|
if (FeatureBitset.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -496,7 +496,7 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
|
||||||
emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_IMPL").str(), OS);
|
emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_IMPL").str(), OS);
|
||||||
|
|
||||||
// The primary data table contains all the fields defined for this map.
|
// 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) {
|
for (unsigned i = 0; i < Table.Entries.size(); ++i) {
|
||||||
Record *Entry = Table.Entries[i];
|
Record *Entry = Table.Entries[i];
|
||||||
OS << " { ";
|
OS << " { ";
|
||||||
|
|
|
@ -103,7 +103,7 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
||||||
assert(!CondStr.empty() && "true predicate should have been filtered");
|
assert(!CondStr.empty() && "true predicate should have been filtered");
|
||||||
|
|
||||||
OS << " if (" << CondStr << ")\n";
|
OS << " if (" << CondStr << ")\n";
|
||||||
OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
|
OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
|
||||||
}
|
}
|
||||||
OS << " return Features;\n";
|
OS << " return Features;\n";
|
||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
|
@ -148,7 +148,7 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
OS << ")\n";
|
OS << ")\n";
|
||||||
OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
|
OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
|
||||||
}
|
}
|
||||||
OS << " return Features;\n";
|
OS << " return Features;\n";
|
||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
|
|
Loading…
Reference in New Issue