X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FSubtargetEmitter.cpp;h=6246d811123deb339f8bd8d6677f5d01a1ecfc32;hb=e3376e6361dfebb435c4292ae27b1766e425e78e;hp=806bda1cbc361e4c8ba500c5fbd6429b8f65c850;hpb=61131ab15fd593a2e295d79fe2714e7bc21f2ec8;p=oota-llvm.git diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 806bda1cbc3..6246d811123 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -11,24 +11,26 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "subtarget-emitter" - #include "CodeGenTarget.h" #include "CodeGenSchedule.h" -#include "llvm/ADT/StringExtras.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 "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" #include #include #include #include + using namespace llvm; +#define DEBUG_TYPE "subtarget-emitter" + namespace { class SubtargetEmitter { // Each processor has a SchedClassDesc table with an entry for each SchedClass. @@ -62,7 +64,7 @@ class SubtargetEmitter { 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, @@ -87,6 +89,8 @@ class SubtargetEmitter { const CodeGenProcModel &ProcModel); Record *FindReadAdvance(const CodeGenSchedRW &SchedRead, const CodeGenProcModel &ProcModel); + void ExpandProcResources(RecVec &PRVec, std::vector &Cycles, + const CodeGenProcModel &ProcModel); void GenSchedClassTables(const CodeGenProcModel &ProcModel, SchedClassTables &SchedTables); void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS); @@ -102,16 +106,14 @@ public: Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {} void run(raw_ostream &o); - }; -} // End anonymous namespace +} // end anonymous namespace // // 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 DefList = Records.getAllDerivedDefinitions(ClassName); std::sort(DefList.begin(), DefList.end(), LessRecord()); @@ -119,50 +121,28 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, 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(); - - // If bit flags then emit expression (1 << i) - if (isBits) OS << " = " << " 1ULL << " << i; + // Open enumeration. Use a 64-bit underlying type. + OS << "enum : uint64_t {\n"; - // 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"; } // @@ -196,22 +176,24 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { 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 &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 << " }"; @@ -253,22 +235,24 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { const std::vector &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 << ","; @@ -384,7 +368,7 @@ EmitStageAndOperandCycleData(raw_ostream &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 FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); @@ -402,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, OS << "}\n"; std::vector BPs = PI->ItinsDef->getValueAsListOfDefs("BP"); - if (BPs.size()) { + if (!BPs.empty()) { OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; @@ -445,17 +429,15 @@ EmitStageAndOperandCycleData(raw_ostream &OS, // If this processor defines no itineraries, then leave the itinerary list // empty. std::vector &ItinList = ProcItinLists.back(); - if (ProcModel.ItinDefList.empty()) + if (!ProcModel.hasItineraries()) continue; - // Reserve index==0 for NoItinerary. - ItinList.resize(SchedModels.numItineraryClasses()+1); - const std::string &Name = ProcModel.ItinsDef->getName(); - // For each itinerary data - for (unsigned SchedClassIdx = 0, - SchedClassEnd = ProcModel.ItinDefList.size(); + ItinList.resize(SchedModels.numInstrSchedClasses()); + assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins"); + + for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size(); SchedClassIdx < SchedClassEnd; ++SchedClassIdx) { // Next itinerary data @@ -565,7 +547,7 @@ EmitItineraries(raw_ostream &OS, 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 @@ -575,12 +557,13 @@ EmitItineraries(raw_ostream &OS, assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); std::vector &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"; @@ -631,13 +614,25 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { Record *PRDef = ProcModel.ProcResourceDefs[i]; - // Find the SuperIdx + Record *SuperDef = nullptr; unsigned SuperIdx = 0; - Record *SuperDef = 0; - if (PRDef->getValueInit("Super")->isComplete()) { - SuperDef = - SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel); - SuperIdx = ProcModel.getProcResourceIdx(SuperDef); + unsigned NumUnits = 0; + 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) { + NumUnits += (*RUI)->getValueAsInt("NumUnits"); + } + } + else { + // Find the SuperIdx + if (PRDef->getValueInit("Super")->isComplete()) { + SuperDef = SchedModels.findProcResUnits( + PRDef->getValueAsDef("Super"), ProcModel); + SuperIdx = ProcModel.getProcResourceIdx(SuperDef); + } + NumUnits = PRDef->getValueAsInt("NumUnits"); } // Emit the ProcResourceDesc if (i+1 == e) @@ -645,8 +640,8 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, OS << " {DBGFIELD(\"" << PRDef->getName() << "\") "; if (PRDef->getName().size() < 15) OS.indent(15 - PRDef->getName().size()); - OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx << ", " - << PRDef->getValueAsBit("Buffered") << "}" << Sep << " // #" << i+1; + OS << NumUnits << ", " << SuperIdx << ", " + << BufferSize << "}" << Sep << " // #" << i+1; if (SuperDef) OS << ", Super=" << SuperDef->getName(); OS << "\n"; @@ -664,7 +659,7 @@ Record *SubtargetEmitter::FindWriteResources( 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 = @@ -684,7 +679,7 @@ Record *SubtargetEmitter::FindWriteResources( 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")) @@ -718,7 +713,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, 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 = @@ -738,7 +733,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, 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")) @@ -763,6 +758,56 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return ResDef; } +// Expand an explicit list of processor resources into a full list of implied +// resource groups and super resources that cover them. +void SubtargetEmitter::ExpandProcResources(RecVec &PRVec, + std::vector &Cycles, + const CodeGenProcModel &PM) { + // Default to 1 resource cycle. + Cycles.resize(PRVec.size(), 1); + for (unsigned i = 0, e = PRVec.size(); i != e; ++i) { + Record *PRDef = PRVec[i]; + RecVec SubResources; + if (PRDef->isSubClassOf("ProcResGroup")) + SubResources = PRDef->getValueAsListOfDefs("Resources"); + else { + SubResources.push_back(PRDef); + PRDef = SchedModels.findProcResUnits(PRVec[i], PM); + for (Record *SubDef = PRDef; + SubDef->getValueInit("Super")->isComplete();) { + if (SubDef->isSubClassOf("ProcResGroup")) { + // Disallow this for simplicitly. + PrintFatalError(SubDef->getLoc(), "Processor resource group " + " cannot be a super resources."); + } + Record *SuperDef = + SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM); + PRVec.push_back(SuperDef); + Cycles.push_back(Cycles[i]); + SubDef = SuperDef; + } + } + for (RecIter PRI = PM.ProcResourceDefs.begin(), + PRE = PM.ProcResourceDefs.end(); + PRI != PRE; ++PRI) { + if (*PRI == PRDef || !(*PRI)->isSubClassOf("ProcResGroup")) + continue; + RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources"); + RecIter SubI = SubResources.begin(), SubE = SubResources.end(); + for( ; SubI != SubE; ++SubI) { + if (std::find(SuperResources.begin(), SuperResources.end(), *SubI) + == SuperResources.end()) { + break; + } + } + if (SubI == SubE) { + PRVec.push_back(*PRI); + Cycles.push_back(Cycles[i]); + } + } + } +} + // Generate the SchedClass table for this processor and update global // tables. Must be called for each processor in order. void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, @@ -787,7 +832,22 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, SCDesc.ReadAdvanceIdx = 0; // A Variant SchedClass has no resources of its own. - if (!SCI->Transitions.empty()) { + bool HasVariants = false; + for (std::vector::const_iterator + TI = SCI->Transitions.begin(), TE = SCI->Transitions.end(); + TI != TE; ++TI) { + if (TI->ProcIndices[0] == 0) { + HasVariants = true; + break; + } + IdxIter PIPos = std::find(TI->ProcIndices.begin(), + TI->ProcIndices.end(), ProcModel.Index); + if (PIPos != TI->ProcIndices.end()) { + HasVariants = true; + break; + } + } + if (HasVariants) { SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps; continue; } @@ -804,29 +864,10 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, } IdxVec Writes = SCI->Writes; IdxVec Reads = SCI->Reads; - if (SCI->ItinClassDef) { - assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs"); - // Check this processor's itinerary class resources. - for (RecIter II = ProcModel.ItinRWDefs.begin(), - IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) { - RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); - if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef) - != Matched.end()) { - SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), - Writes, Reads); - break; - } - } - if (Writes.empty()) { - DEBUG(dbgs() << ProcModel.ItinsDef->getName() - << " does not have resources for itinerary class " - << SCI->ItinClassDef->getName() << '\n'); - } - } - else if (!SCI->InstRWs.empty()) { - // This class may have a default ReadWrite list which can be overriden by + 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"); @@ -842,6 +883,23 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, Writes, Reads); } } + if (Writes.empty()) { + // Check this processor's itinerary class resources. + for (RecIter II = ProcModel.ItinRWDefs.begin(), + IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) { + RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); + if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef) + != Matched.end()) { + SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); + break; + } + } + if (Writes.empty()) { + DEBUG(dbgs() << ProcModel.ModelName + << " does not have resources for class " << SCI->Name << '\n'); + } + } // Sum resources across all operand writes. std::vector WriteProcResources; std::vector WriteLatencies; @@ -859,7 +917,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name); // If this Write is not referenced by a ReadAdvance, don't distinguish it // from other WriteLatency entries. - if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) { + if (!SchedModels.hasReadOfWrite( + SchedModels.getSchedWrite(WriteID).TheDef)) { WriteID = 0; } WLEntry.WriteResourceID = WriteID; @@ -884,16 +943,29 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources"); std::vector Cycles = WriteRes->getValueAsListOfInts("ResourceCycles"); + + ExpandProcResources(PRVec, Cycles, ProcModel); + for (unsigned PRIdx = 0, PREnd = PRVec.size(); PRIdx != PREnd; ++PRIdx) { MCWriteProcResEntry WPREntry; WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]); assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx"); - if (Cycles.size() > PRIdx) - WPREntry.Cycles = Cycles[PRIdx]; - else - WPREntry.Cycles = 1; - WriteProcResources.push_back(WPREntry); + WPREntry.Cycles = Cycles[PRIdx]; + // If this resource is already used in this sequence, add the current + // entry's cycles so that the same resource appears to be used + // serially, rather than multiple parallel uses. This is important for + // in-order machine where the resource consumption is a hazard. + unsigned WPRIdx = 0, WPREnd = WriteProcResources.size(); + for( ; WPRIdx != WPREnd; ++WPRIdx) { + if (WriteProcResources[WPRIdx].ProcResourceIdx + == WPREntry.ProcResourceIdx) { + WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles; + break; + } + } + if (WPRIdx == WPREnd) + WriteProcResources.push_back(WPREntry); } } WriteLatencies.push_back(WLEntry); @@ -1053,7 +1125,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables, continue; std::vector &SCTab = - SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()]; + SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())]; OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup," << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n"; @@ -1062,7 +1134,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables, // The first class is always invalid. We no way to distinguish it except by // name and position. - assert(SchedModels.getSchedClass(0).Name == "NoItinerary" + assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" && "invalid class not first"); OS << " {DBGFIELD(\"InvalidSchedClass\") " << MCSchedClassDesc::InvalidNumMicroOps @@ -1103,12 +1175,22 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { // 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, "MinLatency", ','); + 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" @@ -1117,11 +1199,12 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { << " " << (SchedModels.schedClassEnd() - SchedModels.schedClassBegin()) << ",\n"; else - OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraryClasses()) - OS << " " << PI->ItinsDef->getName() << ");\n"; + OS << " nullptr, nullptr, 0, 0," + << " // No instruction-level machine model.\n"; + if (PI->hasItineraries()) + OS << " " << PI->ItinsDef->getName() << "};\n"; else - OS << " 0); // No Itinerary\n"; + OS << " nullptr}; // No Itinerary\n"; } } @@ -1175,7 +1258,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { << "#define DBGFIELD(x)\n" << "#endif\n"; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { std::vector > ProcItinLists; // Emit the stage data EmitStageAndOperandCycleData(OS, ProcItinLists); @@ -1216,7 +1299,7 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) { if (SCI->Transitions.empty()) continue; - VariantClasses.push_back(SCI - SchedModels.schedClassBegin()); + VariantClasses.push_back(SCI->Index); } if (!VariantClasses.empty()) { OS << " switch (SchedClass) {\n"; @@ -1244,11 +1327,11 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, for (std::vector::const_iterator TI = SC.Transitions.begin(), TE = SC.Transitions.end(); TI != TE; ++TI) { - OS << " if ("; if (*PI != 0 && !std::count(TI->ProcIndices.begin(), TI->ProcIndices.end(), *PI)) { continue; } + OS << " if ("; for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end(); RI != RE; ++RI) { if (RI != TI->PredTerm.begin()) @@ -1263,13 +1346,8 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, if (*PI == 0) break; } - unsigned SCIdx = 0; - if (SC.ItinClassDef) - SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef); - else - SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads); - if (SCIdx != *VCI) - OS << " return " << SCIdx << ";\n"; + if (SC.isInferred()) + OS << " return " << SC.Index << ";\n"; OS << " break;\n"; } OS << " };\n"; @@ -1303,7 +1381,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, } 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 @@ -1313,12 +1391,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 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"; } @@ -1336,8 +1414,8 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_ENUM\n"; OS << "namespace llvm {\n"; - Enumeration(OS, "SubtargetFeature", true); - OS << "} // End llvm namespace \n"; + Enumeration(OS, "SubtargetFeature"); + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; @@ -1358,33 +1436,33 @@ void SubtargetEmitter::run(raw_ostream &OS) { #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 Triple &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, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { 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 << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; @@ -1405,15 +1483,16 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "namespace llvm {\n"; OS << "class DFAPacketizer;\n"; OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" - << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " + << " explicit " << ClassName << "(const Triple &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 << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; @@ -1432,41 +1511,40 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "extern const llvm::MCReadAdvanceEntry " << Target << "ReadAdvanceTable[];\n"; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; OS << "extern const unsigned " << Target << "OperandCycles[];\n"; OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; } - OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " + OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, " << "StringRef FS)\n" - << " : TargetSubtargetInfo() {\n" - << " InitMCSubtargetInfo(TT, CPU, FS, "; + << " : 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); - if (SchedModels.hasItineraryClasses()) { + 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); - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; } @@ -1478,4 +1556,4 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) { SubtargetEmitter(RK, CGTarget).run(OS); } -} // End llvm namespace +} // end llvm namespace