Use std::bitset for SubtargetFeatures.
Previously, subtarget features were a bitfield with the underlying type being uint64_t.
Since several targets (X86 and ARM, in particular) have hit or were very close to hitting this bound, switching the features to use a bitset.
No functional change.
The first several times this was committed (e.g. r229831, r233055), it caused several buildbot failures.
Apparently the reason for most failures was both clang and gcc's inability to deal with large numbers (> 10K) of bitset constructor calls in tablegen-generated initializers of instruction info tables.
This should now be fixed.
llvm-svn: 238192
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index aef3642..9dfdc11 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2248,7 +2248,7 @@
Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(uint64_t FB) const {\n";
+ << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n";
for (const auto &SF : Info.SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
@@ -2270,12 +2270,10 @@
Cond = Cond.substr(1);
}
- OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
+ OS << "(";
if (Neg)
- OS << " == 0";
- else
- OS << " != 0";
- OS << ")";
+ OS << "!";
+ OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";
if (Comma.second.empty())
break;
@@ -2645,7 +2643,7 @@
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
- OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
+ OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector "
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 5db5b35..7905b1a 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -848,7 +848,7 @@
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
- << "uint64_t Bits) {\n";
+ << "const FeatureBitset& Bits) {\n";
Indentation += 2;
if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n";
@@ -1102,10 +1102,10 @@
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) {
if (str[0] == '!')
- o << "!(Bits & " << PredicateNamespace << "::"
- << str.slice(1,str.size()) << ")";
+ o << "!Bits[" << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << "]";
else
- o << "(Bits & " << PredicateNamespace << "::" << str << ")";
+ o << "Bits[" << PredicateNamespace << "::" << str << "]";
}
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
@@ -2012,7 +2012,7 @@
<< " InsnType insn, uint64_t Address,\n"
<< " const void *DisAsm,\n"
<< " const MCSubtargetInfo &STI) {\n"
- << " uint64_t Bits = STI.getFeatureBits();\n"
+ << " const FeatureBitset& Bits = STI.getFeatureBits();\n"
<< "\n"
<< " const uint8_t *Ptr = DecodeTable;\n"
<< " uint32_t CurFieldValue = 0;\n"
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index d007c1d..7b69de56 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -549,15 +549,15 @@
CodeGenTarget &Target = CDP.getTargetInfo();
if (Inst.HasComplexDeprecationPredicate)
// Emit a function pointer to the complex predicate method.
- OS << ",0"
+ OS << ", -1 "
<< ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
else if (!Inst.DeprecatedReason.empty())
// Emit the Subtarget feature.
- OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
- << ",nullptr";
+ OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
+ << " ,nullptr";
else
// Instruction isn't deprecated.
- OS << ",0,nullptr";
+ OS << ", -1 ,nullptr";
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 5ab7b13..de9c7a6 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h"
@@ -62,7 +63,7 @@
CodeGenSchedModels &SchedModels;
std::string Target;
- void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
+ void Enumeration(raw_ostream &OS, const char *ClassName);
unsigned FeatureKeyValues(raw_ostream &OS);
unsigned CPUKeyValues(raw_ostream &OS);
void FormItineraryStageString(const std::string &Names,
@@ -112,8 +113,7 @@
// Enumeration - Emit the specified class as an enumeration.
//
void SubtargetEmitter::Enumeration(raw_ostream &OS,
- const char *ClassName,
- bool isBits) {
+ const char *ClassName) {
// Get all records of class and sort
std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
std::sort(DefList.begin(), DefList.end(), LessRecord());
@@ -121,8 +121,8 @@
unsigned N = DefList.size();
if (N == 0)
return;
- if (N > 64)
- PrintFatalError("Too many (> 64) subtarget features!");
+ if (N > MAX_SUBTARGET_FEATURES)
+ PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
@@ -135,21 +135,14 @@
Record *Def = DefList[i];
// Get and emit name
- OS << " " << Def->getName();
-
- // If bit flags then emit expression (1 << i)
- if (isBits) OS << " = " << " 1ULL << " << i;
-
- // Depending on 'if more in the list' emit comma
+ OS << " " << Def->getName() << " = " << i;
if (++i < N) OS << ",";
OS << "\n";
}
- // Close enumeration
- OS << "};\n";
-
- OS << "}\n";
+ // Close enumeration and namespace
+ OS << "};\n}\n";
}
//
@@ -183,22 +176,24 @@
if (CommandLineName.empty()) continue;
- // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
+ // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
- << Target << "::" << Name << ", ";
+ << "{ " << Target << "::" << Name << " }, ";
const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies");
if (ImpliesList.empty()) {
- OS << "0ULL";
+ OS << "{ }";
} else {
+ OS << "{ ";
for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
OS << Target << "::" << ImpliesList[j]->getName();
- if (++j < M) OS << " | ";
+ if (++j < M) OS << ", ";
}
+ OS << " }";
}
OS << " }";
@@ -240,22 +235,24 @@
const std::vector<Record*> &FeatureList =
Processor->getValueAsListOfDefs("Features");
- // Emit as { "cpu", "description", f1 | f2 | ... fn },
+ // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
OS << " { "
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", ";
if (FeatureList.empty()) {
- OS << "0ULL";
+ OS << "{ }";
} else {
+ OS << "{ ";
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
OS << Target << "::" << FeatureList[j]->getName();
- if (++j < M) OS << " | ";
+ if (++j < M) OS << ", ";
}
+ OS << " }";
}
- // The "0" is for the "implies" section of this data structure.
- OS << ", 0ULL }";
+ // The { } is for the "implies" section of this data structure.
+ OS << ", { } }";
// Depending on 'if more in the list' emit comma
if (++i < N) OS << ",";
@@ -1383,7 +1380,7 @@
}
OS << " InitMCProcessorInfo(CPU, FS);\n"
- << " uint64_t Bits = getFeatureBits();\n";
+ << " const FeatureBitset& Bits = getFeatureBits();\n";
for (unsigned i = 0; i < Features.size(); i++) {
// Next record
@@ -1393,12 +1390,12 @@
const std::string &Attribute = R->getValueAsString("Attribute");
if (Value=="true" || Value=="false")
- OS << " if ((Bits & " << Target << "::"
- << Instance << ") != 0) "
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "]) "
<< Attribute << " = " << Value << ";\n";
else
- OS << " if ((Bits & " << Target << "::"
- << Instance << ") != 0 && "
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "] && "
<< Attribute << " < " << Value << ") "
<< Attribute << " = " << Value << ";\n";
}
@@ -1416,7 +1413,7 @@
OS << "#undef GET_SUBTARGETINFO_ENUM\n";
OS << "namespace llvm {\n";
- Enumeration(OS, "SubtargetFeature", true);
+ Enumeration(OS, "SubtargetFeature");
OS << "} // End llvm namespace \n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";