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
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
|
@ -33,20 +34,117 @@ 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> {
|
||||
/// 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);
|
||||
|
@ -58,23 +156,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(B) {}
|
||||
|
||||
FeatureBitset getAsBitset() const {
|
||||
FeatureBitset Result;
|
||||
|
||||
for (unsigned i = 0, e = Bits.size(); i != e; ++i)
|
||||
Result |= FeatureBitset(Bits[i]) << (64 * i);
|
||||
|
||||
return Result;
|
||||
}
|
||||
const FeatureBitset &getAsBitset() const { return *this; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -313,9 +313,9 @@ struct SysAlias {
|
|||
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;
|
||||
|
@ -326,9 +326,10 @@ struct SysAlias {
|
|||
|
||||
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{
|
||||
|
|
|
@ -119,7 +119,7 @@ HexagonSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
|
|||
|
||||
FeatureBitset Features = getFeatureBits();
|
||||
if (HexagonDisableDuplex)
|
||||
setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
|
||||
setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
|
||||
setFeatureBits(Hexagon_MC::completeHVXFeatures(Features));
|
||||
|
||||
return *this;
|
||||
|
|
|
@ -264,14 +264,12 @@ createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -398,7 +396,7 @@ MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
|
|||
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()));
|
||||
|
|
|
@ -96,9 +96,9 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
|||
// 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: }
|
||||
|
||||
|
@ -106,7 +106,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
|||
// 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: }
|
||||
|
||||
|
|
|
@ -3366,7 +3366,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
|||
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())
|
||||
|
|
|
@ -385,8 +385,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
|
|||
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;
|
||||
|
|
|
@ -496,7 +496,7 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
|
|||
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 << " { ";
|
||||
|
|
|
@ -103,7 +103,7 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
|||
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";
|
||||
|
@ -148,7 +148,7 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
|
|||
} while (true);
|
||||
|
||||
OS << ")\n";
|
||||
OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
|
||||
OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
|
||||
}
|
||||
OS << " return Features;\n";
|
||||
OS << "}\n\n";
|
||||
|
|
Loading…
Reference in New Issue