//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "subtarget-emitter"
-
#include "CodeGenTarget.h"
#include "CodeGenSchedule.h"
#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"
#include <vector>
using namespace llvm;
+#define DEBUG_TYPE "subtarget-emitter"
+
namespace {
class SubtargetEmitter {
// Each processor has a SchedClassDesc table with an entry for each SchedClass.
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,
// 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());
unsigned N = DefList.size();
if (N == 0)
return;
- if (N > 64) {
- errs() << "Too many (> 64) subtarget features!\n";
- exit(1);
- }
+ if (N > MAX_SUBTARGET_FEATURES)
+ PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
- // For bit flag enumerations with more than 32 items, emit constants.
- // Emit an enum for everything else.
- if (isBits && N > 32) {
- // For each record
- for (unsigned i = 0; i < N; i++) {
- // Next record
- Record *Def = DefList[i];
-
- // Get and emit name and expression (1 << i)
- OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
- }
- } else {
- // Open enumeration
- OS << "enum {\n";
-
- // For each record
- for (unsigned i = 0; i < N;) {
- // Next record
- Record *Def = DefList[i];
-
- // Get and emit name
- OS << " " << Def->getName();
+ // Open enumeration. Use a 64-bit underlying type.
+ OS << "enum : uint64_t {\n";
- // If bit flags then emit expression (1 << i)
- if (isBits) OS << " = " << " 1ULL << " << i;
-
- // Depending on 'if more in the list' emit comma
- if (++i < N) OS << ",";
+ // For each record
+ for (unsigned i = 0; i < N;) {
+ // Next record
+ Record *Def = DefList[i];
- OS << "\n";
- }
+ // Get and emit name
+ OS << " " << Def->getName() << " = " << i;
+ if (++i < N) OS << ",";
- // Close enumeration
- OS << "};\n";
+ OS << "\n";
}
- OS << "}\n";
+ // Close enumeration and namespace
+ OS << "};\n}\n";
}
//
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 << " }";
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 << ",";
for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
- if (!ItinsDefSet.insert(PI->ItinsDef))
+ if (!ItinsDefSet.insert(PI->ItinsDef).second)
continue;
std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
OS << "}\n";
std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
- if (BPs.size()) {
+ if (!BPs.empty()) {
OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
Record *ItinsDef = PI->ItinsDef;
- if (!ItinsDefSet.insert(ItinsDef))
+ if (!ItinsDefSet.insert(ItinsDef).second)
continue;
// Get processor itinerary name
assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
+ // Empty itineraries aren't referenced anywhere in the tablegen output
+ // so don't emit them.
+ if (ItinList.empty())
+ continue;
+
OS << "\n";
OS << "static const llvm::InstrItinerary ";
- if (ItinList.empty()) {
- OS << '*' << Name << " = 0;\n";
- continue;
- }
// Begin processor itinerary table
OS << Name << "[] = {\n";
for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
Record *PRDef = ProcModel.ProcResourceDefs[i];
- Record *SuperDef = 0;
+ Record *SuperDef = nullptr;
unsigned SuperIdx = 0;
unsigned NumUnits = 0;
- int BufferSize = -1;
+ int BufferSize = PRDef->getValueAsInt("BufferSize");
if (PRDef->isSubClassOf("ProcResGroup")) {
RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
RUI != RUE; ++RUI) {
- int BuffSz = (*RUI)->getValueAsInt("BufferSize");
- if (!NumUnits || (unsigned)BufferSize < (unsigned)BuffSz)
- BufferSize = BuffSz;
NumUnits += (*RUI)->getValueAsInt("NumUnits");
}
}
SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
}
NumUnits = PRDef->getValueAsInt("NumUnits");
- BufferSize = PRDef->getValueAsInt("BufferSize");
}
// Emit the ProcResourceDesc
if (i+1 == e)
if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
return SchedWrite.TheDef;
- Record *AliasDef = 0;
+ Record *AliasDef = nullptr;
for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
AI != AE; ++AI) {
const CodeGenSchedRW &AliasRW =
return AliasDef;
// Check this processor's list of write resources.
- Record *ResDef = 0;
+ Record *ResDef = nullptr;
for (RecIter WRI = ProcModel.WriteResDefs.begin(),
WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
if (!(*WRI)->isSubClassOf("WriteRes"))
return SchedRead.TheDef;
// Check this processor's list of aliases for SchedRead.
- Record *AliasDef = 0;
+ Record *AliasDef = nullptr;
for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
AI != AE; ++AI) {
const CodeGenSchedRW &AliasRW =
return AliasDef;
// Check this processor's ReadAdvanceList.
- Record *ResDef = 0;
+ Record *ResDef = nullptr;
for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
if (!(*RAI)->isSubClassOf("ReadAdvance"))
if (!SCI->InstRWs.empty()) {
// This class has a default ReadWrite list which can be overriden by
// InstRW definitions.
- Record *RWDef = 0;
+ Record *RWDef = nullptr;
for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
RWI != RWE; ++RWI) {
Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
// Begin processor itinerary properties
OS << "\n";
- OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
+ OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n";
EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
+ EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
+
+ OS << " " << (bool)(PI->ModelDef ?
+ PI->ModelDef->getValueAsBit("PostRAScheduler") : 0)
+ << ", // " << "PostRAScheduler\n";
+
+ OS << " " << (bool)(PI->ModelDef ?
+ PI->ModelDef->getValueAsBit("CompleteModel") : 0)
+ << ", // " << "CompleteModel\n";
+
OS << " " << PI->Index << ", // Processor ID\n";
if (PI->hasInstrSchedModel())
OS << " " << PI->ModelName << "ProcResources" << ",\n"
- SchedModels.schedClassBegin()) << ",\n";
else
OS << " 0, 0, 0, 0, // No instruction-level machine model.\n";
- if (SchedModels.hasItineraries())
- OS << " " << PI->ItinsDef->getName() << ");\n";
+ if (PI->hasItineraries())
+ OS << " " << PI->ItinsDef->getName() << "};\n";
else
- OS << " 0); // No Itinerary\n";
+ OS << " nullptr}; // No Itinerary\n";
}
}
}
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
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";
}
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";
#endif
// MCInstrInfo initialization routine.
- OS << "static inline void Init" << Target
- << "MCSubtargetInfo(MCSubtargetInfo *II, "
- << "StringRef TT, StringRef CPU, StringRef FS) {\n";
- OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
+ OS << "static inline MCSubtargetInfo *create" << Target
+ << "MCSubtargetInfoImpl("
+ << "const TargetTuple &TT, StringRef CPU, StringRef FS) {\n";
+ OS << " return new MCSubtargetInfo(TT, CPU, FS, ";
if (NumFeatures)
OS << Target << "FeatureKV, ";
else
- OS << "0, ";
+ OS << "None, ";
if (NumProcs)
OS << Target << "SubTypeKV, ";
else
- OS << "0, ";
+ OS << "None, ";
OS << '\n'; OS.indent(22);
OS << Target << "ProcSchedKV, "
<< Target << "WriteProcResTable, "
OS << '\n'; OS.indent(22);
OS << Target << "Stages, "
<< Target << "OperandCycles, "
- << Target << "ForwardingPaths, ";
+ << Target << "ForwardingPaths";
} else
- OS << "0, 0, 0, ";
- OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
+ OS << "0, 0, 0";
+ OS << ");\n}\n\n";
OS << "} // End llvm namespace \n";
OS << "namespace llvm {\n";
OS << "class DFAPacketizer;\n";
OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
- << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
+ << " explicit " << ClassName << "(const TargetTuple &TT, StringRef CPU, "
<< "StringRef FS);\n"
<< "public:\n"
- << " unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI,"
- << " const TargetSchedModel *SchedModel) const;\n"
+ << " unsigned resolveSchedClass(unsigned SchedClass, "
+ << " const MachineInstr *DefMI,"
+ << " const TargetSchedModel *SchedModel) const override;\n"
<< " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
<< " const;\n"
<< "};\n";
OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
}
- OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
- << "StringRef FS)\n"
- << " : TargetSubtargetInfo() {\n"
- << " InitMCSubtargetInfo(TT, CPU, FS, ";
+ OS << ClassName << "::" << ClassName
+ << "(const TargetTuple &TT, StringRef CPU, StringRef FS)\n"
+ << " : TargetSubtargetInfo(TT, CPU, FS, ";
if (NumFeatures)
- OS << Target << "FeatureKV, ";
+ OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), ";
else
- OS << "0, ";
+ OS << "None, ";
if (NumProcs)
- OS << Target << "SubTypeKV, ";
+ OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
else
- OS << "0, ";
- OS << '\n'; OS.indent(22);
+ OS << "None, ";
+ OS << '\n'; OS.indent(24);
OS << Target << "ProcSchedKV, "
<< Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
- OS << '\n'; OS.indent(22);
+ OS << '\n'; OS.indent(24);
if (SchedModels.hasItineraries()) {
OS << Target << "Stages, "
<< Target << "OperandCycles, "
- << Target << "ForwardingPaths, ";
+ << Target << "ForwardingPaths";
} else
- OS << "0, 0, 0, ";
- OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
+ OS << "0, 0, 0";
+ OS << ") {}\n\n";
EmitSchedModelHelpers(ClassName, OS);