#define LLVM_MC_SUBTARGETFEATURE_H
#include "llvm/ADT/StringRef.h"
+#include <array>
#include <bitset>
#include <initializer_list>
#include <string>
class raw_ostream;
class Triple;
-const unsigned MAX_SUBTARGET_FEATURES = 192;
+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 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;
+
+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);
+
+ return Result;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// Used to provide key value pairs for feature and CPU bit flags.
const char *Key; ///< K-V key string
const char *Desc; ///< Help descriptor
unsigned Value; ///< K-V integer value
- FeatureBitset Implies; ///< K-V bit mask
+ FeatureBitArray Implies; ///< K-V bit mask
/// Compare routine for std::lower_bound
bool operator<(StringRef S) const {
/// For each feature that is (transitively) implied by this feature, set it.
static
-void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV &FeatureEntry,
+void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (const SubtargetFeatureKV &FE : FeatureTable) {
- if (FeatureEntry.Value == FE.Value) continue;
-
- if (FeatureEntry.Implies.test(FE.Value)) {
+ if (Implies.test(FE.Value)) {
Bits.set(FE.Value);
- SetImpliedBits(Bits, FE, FeatureTable);
+ SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
}
}
}
/// For each feature that (transitively) implies this feature, clear it.
static
-void ClearImpliedBits(FeatureBitset &Bits,
- const SubtargetFeatureKV &FeatureEntry,
+void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (const SubtargetFeatureKV &FE : FeatureTable) {
- if (FeatureEntry.Value == FE.Value) continue;
-
- if (FE.Implies.test(FeatureEntry.Value)) {
+ if (FE.Implies.getAsBitset().test(Value)) {
Bits.reset(FE.Value);
- ClearImpliedBits(Bits, FE, FeatureTable);
+ ClearImpliedBits(Bits, FE.Value, FeatureTable);
}
}
}
if (Bits.test(FeatureEntry->Value)) {
Bits.reset(FeatureEntry->Value);
// For each feature that implies this, clear it.
- ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
} else {
Bits.set(FeatureEntry->Value);
// For each feature that this implies, set it.
- SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
}
} else {
errs() << "'" << Feature << "' is not a recognized feature for this target"
Bits.set(FeatureEntry->Value);
// For each feature that this implies, set it.
- SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
} else {
Bits.reset(FeatureEntry->Value);
// For each feature that implies this, clear it.
- ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
}
} else {
errs() << "'" << Feature << "' is not a recognized feature for this target"
// If there is a match
if (CPUEntry) {
// Set base feature bits
- Bits = CPUEntry->Implies;
+ FeatureBitset CPUImplies = CPUEntry->Implies.getAsBitset();
+ Bits = CPUImplies;
// Set the feature implied by this CPU feature, if any.
for (auto &FE : FeatureTable) {
- if (CPUEntry->Implies.test(FE.Value))
- SetImpliedBits(Bits, FE, FeatureTable);
+ if (CPUImplies.test(FE.Value))
+ SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
}
} else {
errs() << "'" << CPU << "' is not a recognized processor for this target"
CodeGenSchedModels &SchedModels;
std::string Target;
- void Enumeration(raw_ostream &OS);
- unsigned FeatureKeyValues(raw_ostream &OS);
- unsigned CPUKeyValues(raw_ostream &OS);
+ void Enumeration(raw_ostream &OS, DenseMap<Record *, unsigned> &FeatureMap);
+ unsigned FeatureKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap);
+ unsigned CPUKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap);
void FormItineraryStageString(const std::string &Names,
Record *ItinData, std::string &ItinString,
unsigned &NStages);
//
// Enumeration - Emit the specified class as an enumeration.
//
-void SubtargetEmitter::Enumeration(raw_ostream &OS) {
+void SubtargetEmitter::Enumeration(raw_ostream &OS,
+ DenseMap<Record *, unsigned> &FeatureMap) {
// Get all records of class and sort
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("SubtargetFeature");
// Get and emit name
OS << " " << Def->getName() << " = " << i << ",\n";
+
+ // Save the index for this feature.
+ FeatureMap[Def] = i;
}
// Close enumeration and namespace
OS << "} // end namespace " << Target << "\n";
}
+static void printFeatureMask(raw_ostream &OS, RecVec &FeatureList,
+ const DenseMap<Record *, unsigned> &FeatureMap) {
+ std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
+ for (unsigned j = 0, M = FeatureList.size(); j < M; ++j) {
+ unsigned Bit = FeatureMap.lookup(FeatureList[j]);
+ Mask[Bit / 64] |= 1ULL << (Bit % 64);
+ }
+
+ OS << "{ { ";
+ for (unsigned i = 0; i != Mask.size(); ++i) {
+ OS << "0x";
+ OS.write_hex(Mask[i]);
+ OS << "ULL, ";
+ }
+ OS << "} }";
+}
+
//
// FeatureKeyValues - Emit data of all the subtarget features. Used by the
// command line.
//
-unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
+unsigned SubtargetEmitter::FeatureKeyValues(
+ raw_ostream &OS, const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort all the features
std::vector<Record*> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
RecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
- OS << "{";
- for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
- OS << " " << Target << "::" << ImpliesList[j]->getName();
- if (++j < M) OS << ",";
- }
- OS << " } },\n";
+ printFeatureMask(OS, ImpliesList, FeatureMap);
+
+ OS << " },\n";
++NumFeatures;
}
// CPUKeyValues - Emit data of all the subtarget processors. Used by command
// line.
//
-unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
+unsigned
+SubtargetEmitter::CPUKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort processor information
std::vector<Record*> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", 0, ";
- OS << "{";
- for (unsigned j = 0, M = FeatureList.size(); j < M;) {
- OS << " " << Target << "::" << FeatureList[j]->getName();
- if (++j < M) OS << ",";
- }
- OS << " } },\n";
+ printFeatureMask(OS, FeatureList, FeatureMap);
+
+ // The {{}} is for the "implies" section of this data structure.
+ OS << " },\n";
}
// End processor table
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
+ DenseMap<Record *, unsigned> FeatureMap;
+
OS << "namespace llvm {\n";
- Enumeration(OS);
+ Enumeration(OS, FeatureMap);
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
#if 0
OS << "namespace {\n";
#endif
- unsigned NumFeatures = FeatureKeyValues(OS);
+ unsigned NumFeatures = FeatureKeyValues(OS, FeatureMap);
OS << "\n";
- unsigned NumProcs = CPUKeyValues(OS);
+ unsigned NumProcs = CPUKeyValues(OS, FeatureMap);
OS << "\n";
EmitSchedModel(OS);
OS << "\n";