diff options
author | Jim Laskey <jlaskey@mac.com> | 2005-10-27 19:47:21 +0000 |
---|---|---|
committer | Jim Laskey <jlaskey@mac.com> | 2005-10-27 19:47:21 +0000 |
commit | 0d841e05677bdc55d003720e85e12d28dfe31862 (patch) | |
tree | 6dd04484d919f9a0ee6924bc3ab9b24ce1198396 /utils/TableGen/SubtargetEmitter.cpp | |
parent | 15517be4bfc7ec7e60ecb25dc0bb46de27d3de37 (diff) | |
download | llvm-0d841e05677bdc55d003720e85e12d28dfe31862.tar.gz llvm-0d841e05677bdc55d003720e85e12d28dfe31862.tar.bz2 llvm-0d841e05677bdc55d003720e85e12d28dfe31862.tar.xz |
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
Diffstat (limited to 'utils/TableGen/SubtargetEmitter.cpp')
-rw-r--r-- | utils/TableGen/SubtargetEmitter.cpp | 221 |
1 files changed, 190 insertions, 31 deletions
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 30d27c1745..7c06cf5148 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 <algorithm> -#include <set> using namespace llvm; // // Convenience types. // typedef std::vector<Record*> RecordList; -typedef std::vector<Record*>::iterator RecordListIter; + +struct RecordListIter { + std::vector<Record*>::iterator RI; + std::vector<Record*>::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<DefInit*>(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<DefInit*>(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"; @@ -148,6 +170,140 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { } // +// 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); } |