llvm.org GIT mirror llvm / 4acc3db
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369847 91177308-0d34-0410-b5e6-96231b3b80d8 Benjamin Kramer 26 days ago
9 changed file(s) with 130 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
1717 #define LLVM_MC_SUBTARGETFEATURE_H
1818
1919 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/MathExtras.h"
2021 #include
2122 #include
2223 #include
3233 const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
3334
3435 /// Container class for subtarget features.
35 /// This is convenient because std::bitset does not have a constructor
36 /// with an initializer list of set bits.
37 class FeatureBitset : public std::bitset {
36 /// This is a constexpr reimplementation of a subset of std::bitset. It would be
37 /// nice to use std::bitset directly, but it doesn't support constant
38 /// initialization.
39 class FeatureBitset {
40 static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
41 "Should be a multiple of 64!");
42 // This cannot be a std::array, operator[] is not constexpr until C++17.
43 uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
44
45 protected:
46 constexpr FeatureBitset(const std::array &B) {
47 for (unsigned I = 0; I != B.size(); ++I)
48 Bits[I] = B[I];
49 }
50
3851 public:
39 // Cannot inherit constructors because it's not supported by VC++..
4052 FeatureBitset() = default;
41
42 FeatureBitset(const bitset& B) : bitset(B) {}
43
44 FeatureBitset(std::initializer_list Init) {
53 constexpr FeatureBitset(std::initializer_list Init) {
4554 for (auto I : Init)
4655 set(I);
4756 }
57
58 FeatureBitset &set() {
59 std::fill(std::begin(Bits), std::end(Bits), -1ULL);
60 return *this;
61 }
62
63 constexpr FeatureBitset &set(unsigned I) {
64 Bits[I / 64] |= uint64_t(1) << (I % 64);
65 return *this;
66 }
67
68 constexpr FeatureBitset &reset(unsigned I) {
69 Bits[I / 64] &= ~(uint64_t(1) << (I % 64));
70 return *this;
71 }
72
73 constexpr FeatureBitset &flip(unsigned I) {
74 Bits[I / 64] ^= uint64_t(1) << (I % 64);
75 return *this;
76 }
77
78 constexpr bool operator[](unsigned I) const {
79 uint64_t Mask = uint64_t(1) << (I % 64);
80 return (Bits[I / 64] & Mask) != 0;
81 }
82
83 constexpr bool test(unsigned I) const { return (*this)[I]; }
84
85 constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
86
87 bool any() const {
88 return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
89 }
90 bool none() const { return !any(); }
91 size_t count() const {
92 size_t Count = 0;
93 for (auto B : Bits)
94 Count += countPopulation(B);
95 return Count;
96 }
97
98 constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
99 for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
100 Bits[I] ^= RHS.Bits[I];
101 }
102 return *this;
103 }
104 constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
105 FeatureBitset Result = *this;
106 Result ^= RHS;
107 return Result;
108 }
109
110 constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
111 for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
112 Bits[I] &= RHS.Bits[I];
113 }
114 return *this;
115 }
116 constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
117 FeatureBitset Result = *this;
118 Result &= RHS;
119 return Result;
120 }
121
122 constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
123 for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
124 Bits[I] |= RHS.Bits[I];
125 }
126 return *this;
127 }
128 constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
129 FeatureBitset Result = *this;
130 Result |= RHS;
131 return Result;
132 }
133
134 constexpr FeatureBitset operator~() const {
135 FeatureBitset Result = *this;
136 for (auto &B : Result.Bits)
137 B = ~B;
138 return Result;
139 }
140
141 bool operator==(const FeatureBitset &RHS) const {
142 return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
143 }
144
145 bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
48146
49147 bool operator < (const FeatureBitset &Other) const {
50148 for (unsigned I = 0, E = size(); I != E; ++I) {
57155 };
58156
59157 /// Class used to store the subtarget bits in the tables created by tablegen.
60 /// The std::initializer_list constructor of FeatureBitset can't be done at
61 /// compile time and requires a static constructor to run at startup.
62 class FeatureBitArray {
63 std::array Bits;
64
158 class FeatureBitArray : public FeatureBitset {
65159 public:
66160 constexpr FeatureBitArray(const std::array &B)
67 : Bits(B) {}
68
69 FeatureBitset getAsBitset() const {
70 FeatureBitset Result;
71
72 for (unsigned i = 0, e = Bits.size(); i != e; ++i)
73 Result |= FeatureBitset(Bits[i]) << (64 * i);
74
75 return Result;
76 }
161 : FeatureBitset(B) {}
162
163 const FeatureBitset &getAsBitset() const { return *this; }
77164 };
78165
79166 //===----------------------------------------------------------------------===//
312312 uint16_t Encoding;
313313 FeatureBitset FeaturesRequired;
314314
315 SysAlias (const char *N, uint16_t E) : Name(N), Encoding(E) {};
316 SysAlias (const char *N, uint16_t E, FeatureBitset F) :
317 Name(N), Encoding(E), FeaturesRequired(F) {};
315 constexpr SysAlias(const char *N, uint16_t E) : Name(N), Encoding(E) {}
316 constexpr SysAlias(const char *N, uint16_t E, FeatureBitset F)
317 : Name(N), Encoding(E), FeaturesRequired(F) {}
318318
319319 bool haveFeatures(FeatureBitset ActiveFeatures) const {
320320 return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
325325
326326 struct SysAliasReg : SysAlias {
327327 bool NeedsReg;
328 SysAliasReg(const char *N, uint16_t E, bool R) : SysAlias(N, E), NeedsReg(R) {};
329 SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F) : SysAlias(N, E, F),
330 NeedsReg(R) {};
328 constexpr SysAliasReg(const char *N, uint16_t E, bool R)
329 : SysAlias(N, E), NeedsReg(R) {}
330 constexpr SysAliasReg(const char *N, uint16_t E, bool R, FeatureBitset F)
331 : SysAlias(N, E, F), NeedsReg(R) {}
331332 };
332333
333334 namespace AArch64AT{
118118
119119 FeatureBitset Features = getFeatureBits();
120120 if (HexagonDisableDuplex)
121 setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
121 setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
122122 setFeatureBits(Hexagon_MC::completeHVXFeatures(Features));
123123
124124 return *this;
263263 }
264264
265265 static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
266 uint64_t FB = STI->getFeatureBits().to_ullong();
267 if (FB & (1ULL << F))
266 if (STI->getFeatureBits()[F])
268267 STI->ToggleFeature(F);
269268 }
270269
271270 static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
272 uint64_t FB = STI->getFeatureBits().to_ullong();
273 return (FB & (1ULL << F)) != 0;
271 return STI->getFeatureBits()[F];
274272 }
275273
276274 namespace {
397395 MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
398396 if (HexagonDisableDuplex) {
399397 llvm::FeatureBitset Features = X->getFeatureBits();
400 X->setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
398 X->setFeatureBits(Features.reset(Hexagon::FeatureDuplex));
401399 }
402400
403401 X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));
9595 // CHECK-NEXT: computeAvailableModuleFeatures(const MyTargetSubtarget *Subtarget) const {
9696 // CHECK-NEXT: PredicateBitset Features;
9797 // CHECK-NEXT: if (Subtarget->hasA())
98 // CHECK-NEXT: Features[Feature_HasABit] = 1;
98 // CHECK-NEXT: Features.set(Feature_HasABit);
9999 // CHECK-NEXT: if (Subtarget->hasB())
100 // CHECK-NEXT: Features[Feature_HasBBit] = 1;
100 // CHECK-NEXT: Features.set(Feature_HasBBit);
101101 // CHECK-NEXT: return Features;
102102 // CHECK-NEXT: }
103103
105105 // CHECK-NEXT: computeAvailableFunctionFeatures(const MyTargetSubtarget *Subtarget, const MachineFunction *MF) const {
106106 // CHECK-NEXT: PredicateBitset Features;
107107 // CHECK-NEXT: if (Subtarget->hasC())
108 // CHECK-NEXT: Features[Feature_HasCBit] = 1;
108 // CHECK-NEXT: Features.set(Feature_HasCBit);
109109 // CHECK-NEXT: return Features;
110110 // CHECK-NEXT: }
111111
33653365 OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
33663366 }
33673367 OS << "};\n\n"
3368 << "const static FeatureBitset FeatureBitsets[] {\n"
3368 << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
33693369 << " {}, // AMFBS_None\n";
33703370 for (const auto &FeatureBitset : FeatureBitsets) {
33713371 if (FeatureBitset.empty())
384384 o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
385385 }
386386 o << "};\n\n"
387 << "const static FeatureBitset FeatureBitsets[] {\n"
388 << " {}, // CEFBS_None\n";
387 << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
388 << " {}, // CEFBS_None\n";
389389 for (const auto &FeatureBitset : FeatureBitsets) {
390390 if (FeatureBitset.empty())
391391 continue;
495495 emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_IMPL").str(), OS);
496496
497497 // The primary data table contains all the fields defined for this map.
498 OS << "const " << Table.CppTypeName << " " << Table.Name << "[] = {\n";
498 OS << "constexpr " << Table.CppTypeName << " " << Table.Name << "[] = {\n";
499499 for (unsigned i = 0; i < Table.Entries.size(); ++i) {
500500 Record *Entry = Table.Entries[i];
501501 OS << " { ";
102102 assert(!CondStr.empty() && "true predicate should have been filtered");
103103
104104 OS << " if (" << CondStr << ")\n";
105 OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
105 OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
106106 }
107107 OS << " return Features;\n";
108108 OS << "}\n\n";
147147 } while (true);
148148
149149 OS << ")\n";
150 OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
150 OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
151151 }
152152 OS << " return Features;\n";
153153 OS << "}\n\n";