From 0d841e05677bdc55d003720e85e12d28dfe31862 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Thu, 27 Oct 2005 19:47:21 +0000 Subject: [PATCH] Now generating instruction itineraries for scheduling. Not my best work, but... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24050 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/SubtargetEmitter.cpp | 221 ++++++++++++++++++++++++---- utils/TableGen/SubtargetEmitter.h | 22 ++- 2 files changed, 211 insertions(+), 32 deletions(-) diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 30d27c17454..7c06cf5148b 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -16,15 +16,46 @@ #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" -#include -#include using namespace llvm; // // Convenience types. // typedef std::vector RecordList; -typedef std::vector::iterator RecordListIter; + +struct RecordListIter { + std::vector::iterator RI; + std::vector::iterator E; + + RecordListIter(RecordList &RL) + : RI(RL.begin()), E(RL.end()) + {} + + bool isMore() const { return RI != E; } + + Record *next() { return isMore() ? *RI++ : NULL; } +}; + +struct DefListIter { + ListInit *List; + unsigned N; + unsigned i; + + DefListIter(Record *R, const std::string &Name) + : List(R->getValueAsListInit(Name)), N(List->getSize()), i(0) + {} + + bool isMore() const { return i < N; } + + Record *next() { + if (isMore()) { + if (DefInit *DI = dynamic_cast(List->getElement(i++))) { + return DI->getDef(); + } + } + return NULL; + } +}; // // Record sort by name function. @@ -57,8 +88,8 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, OS << "enum {\n"; - for (RecordListIter RI = Defs.begin(), E = Defs.end(); RI != E;) { - Record *R = *RI++; + RecordListIter DI(Defs); + while (Record *R = DI.next()) { std::string Instance = R->getName(); OS << " " << Instance; @@ -66,7 +97,7 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, OS << " = " << " 1 << " << i++; } - OS << ((RI != E) ? ",\n" : "\n"); + OS << (DI.isMore() ? ",\n" : "\n"); } OS << "};\n"; @@ -82,8 +113,8 @@ void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { OS << "// Sorted (by key) array of values for CPU features.\n" << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n"; - for (RecordListIter RI = Features.begin(), E = Features.end(); RI != E;) { - Record *R = *RI++; + RecordListIter FI(Features); + while (Record *R = FI.next()) { std::string Instance = R->getName(); std::string Name = R->getValueAsString("Name"); std::string Desc = R->getValueAsString("Desc"); @@ -91,7 +122,7 @@ void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { << "\"" << Name << "\", " << "\"" << Desc << "\", " << Instance - << ((RI != E) ? " },\n" : " }\n"); + << (FI.isMore() ? " },\n" : " }\n"); } OS << "};\n"; @@ -110,35 +141,26 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { OS << "// Sorted (by key) array of values for CPU subtype.\n" << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n"; - for (RecordListIter RI = Processors.begin(), E = Processors.end(); - RI != E;) { - Record *R = *RI++; + RecordListIter PI(Processors); + while (Record *R = PI.next()) { std::string Name = R->getValueAsString("Name"); - Record *ProcItin = R->getValueAsDef("ProcItin"); - ListInit *Features = R->getValueAsListInit("Features"); - unsigned N = Features->getSize(); + DefListIter FI(R, "Features"); + OS << " { " << "\"" << Name << "\", " << "\"Select the " << Name << " processor\", "; - - if (N == 0) { + if (!FI.isMore()) { OS << "0"; } else { - for (unsigned i = 0; i < N; ) { - if (DefInit *DI = dynamic_cast(Features->getElement(i++))) { - Record *Feature = DI->getDef(); - std::string Name = Feature->getName(); - OS << Name; - if (i != N) OS << " | "; - } else { - throw "Feature: " + Name + - " expected feature in processor feature list!"; - } + while (Record *Feature = FI.next()) { + std::string Name = Feature->getName(); + OS << Name; + if (FI.isMore()) OS << " | "; } } - OS << ((RI != E) ? " },\n" : " }\n"); + OS << (PI.isMore() ? " },\n" : " }\n"); } OS << "};\n"; @@ -147,6 +169,140 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { OS<<"};\n"; } +// +// CollectAllItinClasses - Gathers and enumerates all the itinerary classes. +// +unsigned SubtargetEmitter::CollectAllItinClasses(IntMap &ItinClassesMap) { + RecordList ICL = Records.getAllDerivedDefinitions("InstrItinClass"); + sort(ICL.begin(), ICL.end(), LessRecord()); + + RecordListIter ICI(ICL); + unsigned Index = 0; + while (Record *ItinClass = ICI.next()) { + std::string Name = ItinClass->getName(); + ItinClassesMap[Name] = Index++; + } + + return Index; +} + +// +// FormItineraryString - Compose a string containing the data initialization +// for the specified itinerary. N is the number of stages. +// +void SubtargetEmitter::FormItineraryString(Record *ItinData, + std::string &ItinString, + unsigned &N) { + DefListIter SLI(ItinData, "Stages"); + N = SLI.N; + while (Record *Stage = SLI.next()) { + int Cycles = Stage->getValueAsInt("Cycles"); + ItinString += " ,{ " + itostr(Cycles) + ", "; + + DefListIter ULI(Stage, "Units"); + while (Record *Unit = ULI.next()) { + std::string Name = Unit->getName(); + ItinString += Name; + if (ULI.isMore())ItinString += " | "; + } + } + + ItinString += " }"; +} + +// +// EmitStageData - Generate unique itinerary stages. Record itineraries for +// processors. +// +void SubtargetEmitter::EmitStageData(std::ostream &OS, + unsigned N, + IntMap &ItinClassesMap, + ProcessorList &ProcList) { + OS << "static llvm::InstrStage Stages[] = {\n" + " { 0, 0 } // No itinerary\n"; + + IntMap ItinMap; + unsigned Index = 1; + RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries"); + RecordListIter II(Itins); + while (Record *Itin = II.next()) { + std::string Name = Itin->getName(); + if (Name == "NoItineraries") continue; + + IntineraryList IL; + IL.resize(N); + + DefListIter IDLI(Itin, "IID"); + while (Record *ItinData = IDLI.next()) { + std::string ItinString; + unsigned M; + FormItineraryString(ItinData, ItinString, M); + + unsigned Find = ItinMap[ItinString]; + + if (Find == 0) { + OS << ItinString << " // " << Index << "\n"; + ItinMap[ItinString] = Find = Index++; + } + + InstrItinerary Intinerary = { Find, Find + M }; + + std::string Name = ItinData->getValueAsDef("TheClass")->getName(); + Find = ItinClassesMap[Name]; + IL[Find] = Intinerary; + } + + ProcList.push_back(IL); + } + + OS << "};\n"; +} + +// +// EmitProcessData - Generate data for processor itineraries. +// +void SubtargetEmitter::EmitProcessData(std::ostream &OS, + ProcessorList &ProcList) { + ProcessorList::iterator PLI = ProcList.begin(); + RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries"); + RecordListIter II(Itins); + while (Record *Itin = II.next()) { + std::string Name = Itin->getName(); + if (Name == "NoItineraries") continue; + + OS << "\n"; + OS << "static llvm::InstrItinerary " << Name << "[] = {\n"; + + IntineraryList &IL = *PLI++; + unsigned Index = 0; + for (IntineraryList::iterator ILI = IL.begin(), E = IL.end(); ILI != E;) { + InstrItinerary &Intinerary = *ILI++; + + if (Intinerary.First == 0) { + OS << " { 0, 0 }"; + } else { + OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }"; + } + + if (ILI != E) OS << ","; + OS << " // " << Index++ << "\n"; + } + OS << "};\n"; + } +} + +// +// EmitData - Emits all stages and itineries, folding common patterns. +// +void SubtargetEmitter::EmitData(std::ostream &OS) { + IntMap ItinClassesMap; + ProcessorList ProcList; + + unsigned N = CollectAllItinClasses(ItinClassesMap); + EmitStageData(OS, N, ItinClassesMap, ProcList); + EmitProcessData(OS, ProcList); +} + // // ParseFeaturesFunction - Produces a subtarget specific function for parsing // the subtarget features string. @@ -166,8 +322,8 @@ void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) { " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" " FeatureKV, FeatureKVSize);\n"; - for (RecordListIter RI = Features.begin(), E = Features.end(); RI != E;) { - Record *R = *RI++; + RecordListIter FI(Features); + while (Record *R = FI.next()) { std::string Instance = R->getName(); std::string Name = R->getValueAsString("Name"); std::string Type = R->getValueAsString("Type"); @@ -186,7 +342,8 @@ void SubtargetEmitter::run(std::ostream &OS) { EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); - OS << "#include \"llvm/Target/SubtargetFeature.h\"\n\n"; + OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; + OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; Enumeration(OS, "FuncUnit", true); OS<<"\n"; @@ -198,5 +355,7 @@ void SubtargetEmitter::run(std::ostream &OS) { OS<<"\n"; CPUKeyValues(OS); OS<<"\n"; + EmitData(OS); + OS<<"\n"; ParseFeaturesFunction(OS); } diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index 7e2a7cb0a37..2a7b70be25d 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -15,17 +15,37 @@ #define SUBTARGET_EMITTER_H #include "TableGenBackend.h" +#include "llvm/Target/TargetInstrItineraries.h" +#include +#include +#include + namespace llvm { +// +// Convenience types. +// +typedef std::map IntMap; +typedef std::vector IntineraryList; +typedef std::vector ProcessorList; + class SubtargetEmitter : public TableGenBackend { + RecordKeeper &Records; std::string Target; void Enumeration(std::ostream &OS, const char *ClassName, bool isBits); void FeatureKeyValues(std::ostream &OS); void CPUKeyValues(std::ostream &OS); - void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS); + unsigned CollectAllItinClasses(IntMap &ItinClassesMap); + void FormItineraryString(Record *ItinData, std::string &ItinString, + unsigned &N); + void EmitStageData(std::ostream &OS, unsigned N, + IntMap &ItinClassesMap, ProcessorList &ProcList); + void EmitProcessData(std::ostream &OS, ProcessorList &ProcList); + void EmitData(std::ostream &OS); + void ParseFeaturesFunction(std::ostream &OS); public: SubtargetEmitter(RecordKeeper &R) : Records(R) {} -- 2.34.1