diff options
-rw-r--r-- | utils/TableGen/CodeGenSchedule.cpp | 234 | ||||
-rw-r--r-- | utils/TableGen/CodeGenSchedule.h | 67 | ||||
-rw-r--r-- | utils/TableGen/SubtargetEmitter.cpp | 78 |
3 files changed, 174 insertions, 205 deletions
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 0b1fb6c..e3a6fe1 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -88,7 +88,7 @@ struct InstRegexOp : public SetTheory::Operator { /// CodeGenModels ctor interprets machine model records and populates maps. CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK, const CodeGenTarget &TGT): - Records(RK), Target(TGT), NumItineraryClasses(0) { + Records(RK), Target(TGT) { Sets.addFieldExpander("InstRW", "Instrs"); @@ -502,40 +502,25 @@ void CodeGenSchedModels::collectSchedClasses() { // NoItinerary is always the first class at Idx=0 SchedClasses.resize(1); - SchedClasses.back().Name = "NoItinerary"; + SchedClasses.back().Index = 0; + SchedClasses.back().Name = "NoInstrModel"; + SchedClasses.back().ItinClassDef = Records.getDef("NoItinerary"); SchedClasses.back().ProcIndices.push_back(0); - SchedClassIdxMap[SchedClasses.back().Name] = 0; - // Gather and sort all itinerary classes used by instruction descriptions. - RecVec ItinClassList; + // Create a SchedClass for each unique combination of itinerary class and + // SchedRW list. for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary"); - // Map a new SchedClass with no index. - if (!SchedClassIdxMap.count(ItinDef->getName())) { - SchedClassIdxMap[ItinDef->getName()] = 0; - ItinClassList.push_back(ItinDef); - } - } - // Assign each itinerary class unique number, skipping NoItinerary==0 - NumItineraryClasses = ItinClassList.size(); - std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); - for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) { - Record *ItinDef = ItinClassList[i]; - SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size(); - SchedClasses.push_back(CodeGenSchedClass(ItinDef)); - } - // Infer classes from SchedReadWrite resources listed for each - // instruction definition that inherits from class Sched. - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - if ((*I)->TheDef->isValueUnset("SchedRW")) - continue; IdxVec Writes, Reads; - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + if (!(*I)->TheDef->isValueUnset("SchedRW")) + findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + // ProcIdx == 0 indicates the class applies to all processors. IdxVec ProcIndices(1, 0); - addSchedClass(Writes, Reads, ProcIndices); + + unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices); + InstrClassMap[(*I)->TheDef] = SCIdx; } // Create classes for InstRW defs. RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW"); @@ -549,68 +534,70 @@ void CodeGenSchedModels::collectSchedClasses() { DEBUG(EnableDump = true); if (!EnableDump) return; + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { - Record *SchedDef = (*I)->TheDef; + std::string InstName = (*I)->TheDef->getName(); - if (!SchedDef->isValueUnset("SchedRW")) { + unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); + if (!SCIdx) { + dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + continue; + } + CodeGenSchedClass &SC = getSchedClass(SCIdx); + if (SC.ProcIndices[0] != 0) + PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class " + "must not be subtarget specific."); + + IdxVec ProcIndices; + if (SC.ItinClassDef->getName() != "NoItinerary") { + ProcIndices.push_back(0); + dbgs() << "Itinerary for " << InstName << ": " + << SC.ItinClassDef->getName() << '\n'; + } + if (!SC.Writes.empty()) { + ProcIndices.push_back(0); + dbgs() << "SchedRW machine model for " << InstName; + for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; ++WI) + dbgs() << " " << SchedWrites[*WI].Name; + for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI) + dbgs() << " " << SchedReads[*RI].Name; + dbgs() << '\n'; + } + const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs; + for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); + RWI != RWE; ++RWI) { + const CodeGenProcModel &ProcModel = + getProcModel((*RWI)->getValueAsDef("SchedModel")); + ProcIndices.push_back(ProcModel.Index); + dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName; IdxVec Writes; IdxVec Reads; - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); - dbgs() << "SchedRW machine model for " << InstName; + findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) dbgs() << " " << SchedWrites[*WI].Name; for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) dbgs() << " " << SchedReads[*RI].Name; dbgs() << '\n'; } - unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); - if (SCIdx) { - const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs; - for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); - RWI != RWE; ++RWI) { - const CodeGenProcModel &ProcModel = - getProcModel((*RWI)->getValueAsDef("SchedModel")); - dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName; - IdxVec Writes; - IdxVec Reads; - findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), - Writes, Reads); - for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) - dbgs() << " " << SchedWrites[*WI].Name; - for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) - dbgs() << " " << SchedReads[*RI].Name; - dbgs() << '\n'; - } - continue; - } - if (SchedDef->isValueUnset("SchedRW") - && (SchedDef->getValueAsDef("Itinerary")->getName() == "NoItinerary")) { - dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), + PE = ProcModels.end(); PI != PE; ++PI) { + if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) + dbgs() << "No machine model for " << (*I)->TheDef->getName() + << " on processor " << PI->ModelName << '\n'; } } } -unsigned CodeGenSchedModels::getSchedClassIdx( - const RecVec &RWDefs) const { - - IdxVec Writes, Reads; - findRWs(RWDefs, Writes, Reads); - return findSchedClassIdx(Writes, Reads); -} - /// Find an SchedClass that has been inferred from a per-operand list of /// SchedWrites and SchedReads. -unsigned CodeGenSchedModels::findSchedClassIdx(const IdxVec &Writes, +unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef, + const IdxVec &Writes, const IdxVec &Reads) const { for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) { - // Classes with InstRWs may have the same Writes/Reads as a class originally - // produced by a SchedRW definition. We need to be able to recover the - // original class index for processors that don't match any InstRWs. - if (I->ItinClassDef || !I->InstRWs.empty()) - continue; - - if (I->Writes == Writes && I->Reads == Reads) { + if (I->ItinClassDef == ItinClassDef + && I->Writes == Writes && I->Reads == Reads) { return I - schedClassBegin(); } } @@ -621,29 +608,17 @@ unsigned CodeGenSchedModels::findSchedClassIdx(const IdxVec &Writes, unsigned CodeGenSchedModels::getSchedClassIdx( const CodeGenInstruction &Inst) const { - unsigned SCIdx = InstrClassMap.lookup(Inst.TheDef); - if (SCIdx) - return SCIdx; - - // If this opcode isn't mapped by the subtarget fallback to the instruction - // definition's SchedRW or ItinDef values. - if (!Inst.TheDef->isValueUnset("SchedRW")) { - RecVec RWs = Inst.TheDef->getValueAsListOfDefs("SchedRW"); - return getSchedClassIdx(RWs); - } - Record *ItinDef = Inst.TheDef->getValueAsDef("Itinerary"); - assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass"); - unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName()); - assert(Idx <= NumItineraryClasses && "bad ItinClass index"); - return Idx; + return InstrClassMap.lookup(Inst.TheDef); } std::string CodeGenSchedModels::createSchedClassName( - const IdxVec &OperWrites, const IdxVec &OperReads) { + Record *ItinClassDef, const IdxVec &OperWrites, const IdxVec &OperReads) { std::string Name; + if (ItinClassDef && ItinClassDef->getName() != "NoItinerary") + Name = ItinClassDef->getName(); for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) { - if (WI != OperWrites.begin()) + if (!Name.empty()) Name += '_'; Name += SchedWrites[*WI].Name; } @@ -665,17 +640,18 @@ std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) { return Name; } -/// Add an inferred sched class from a per-operand list of SchedWrites and -/// SchedReads. ProcIndices contains the set of IDs of processors that may -/// utilize this class. -unsigned CodeGenSchedModels::addSchedClass(const IdxVec &OperWrites, +/// Add an inferred sched class from an itinerary class and per-operand list of +/// SchedWrites and SchedReads. ProcIndices contains the set of IDs of +/// processors that may utilize this class. +unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef, + const IdxVec &OperWrites, const IdxVec &OperReads, const IdxVec &ProcIndices) { assert(!ProcIndices.empty() && "expect at least one ProcIdx"); - unsigned Idx = findSchedClassIdx(OperWrites, OperReads); - if (Idx) { + unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads); + if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) { IdxVec PI; std::set_union(SchedClasses[Idx].ProcIndices.begin(), SchedClasses[Idx].ProcIndices.end(), @@ -687,7 +663,9 @@ unsigned CodeGenSchedModels::addSchedClass(const IdxVec &OperWrites, Idx = SchedClasses.size(); SchedClasses.resize(Idx+1); CodeGenSchedClass &SC = SchedClasses.back(); - SC.Name = createSchedClassName(OperWrites, OperReads); + SC.Index = Idx; + SC.Name = createSchedClassName(ItinClassDef, OperWrites, OperReads); + SC.ItinClassDef = ItinClassDef; SC.Writes = OperWrites; SC.Reads = OperReads; SC.ProcIndices = ProcIndices; @@ -709,19 +687,10 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes"); for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) { - unsigned SCIdx = 0; InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I); - if (Pos != InstrClassMap.end()) - SCIdx = Pos->second; - else { - // This instruction has not been mapped yet. Get the original class. All - // instructions in the same InstrRW class must be from the same original - // class because that is the fall-back class for other processors. - Record *ItinDef = (*I)->getValueAsDef("Itinerary"); - SCIdx = SchedClassIdxMap.lookup(ItinDef->getName()); - if (!SCIdx && !(*I)->isValueUnset("SchedRW")) - SCIdx = getSchedClassIdx((*I)->getValueAsListOfDefs("SchedRW")); - } + if (Pos == InstrClassMap.end()) + PrintFatalError((*I)->getLoc(), "No sched class for instruction."); + unsigned SCIdx = Pos->second; unsigned CIdx = 0, CEnd = ClassInstrs.size(); for (; CIdx != CEnd; ++CIdx) { if (ClassInstrs[CIdx].first == SCIdx) @@ -741,7 +710,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second; // If the all instrs in the current class are accounted for, then leave // them mapped to their old class. - if (SchedClasses[OldSCIdx].InstRWs.size() == InstDefs.size()) { + if (OldSCIdx && SchedClasses[OldSCIdx].InstRWs.size() == InstDefs.size()) { assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 && "expected a generic SchedClass"); continue; @@ -749,6 +718,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { unsigned SCIdx = SchedClasses.size(); SchedClasses.resize(SCIdx+1); CodeGenSchedClass &SC = SchedClasses.back(); + SC.Index = SCIdx; SC.Name = createSchedClassName(InstDefs); // Preserve ItinDef and Writes/Reads for processors without an InstRW entry. SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef; @@ -780,32 +750,46 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { } } +// True if collectProcItins found anything. +bool CodeGenSchedModels::hasItineraries() const { + for (CodeGenSchedModels::ProcIter PI = procModelBegin(), PE = procModelEnd(); + PI != PE; ++PI) { + if (PI->hasItineraries()) + return true; + } + return false; +} + // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(), PE = ProcModels.end(); PI != PE; ++PI) { CodeGenProcModel &ProcModel = *PI; - RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID"); - // Skip empty itinerary. - if (ItinRecords.empty()) + if (!ProcModel.hasItineraries()) continue; - ProcModel.ItinDefList.resize(NumItineraryClasses+1); + RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID"); + assert(!ItinRecords.empty() && "ProcModel.hasItineraries is incorrect"); + + // Populate ItinDefList with Itinerary records. + ProcModel.ItinDefList.resize(NumInstrSchedClasses); // Insert each itinerary data record in the correct position within // the processor model's ItinDefList. for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) { Record *ItinData = ItinRecords[i]; Record *ItinDef = ItinData->getValueAsDef("TheClass"); - if (!SchedClassIdxMap.count(ItinDef->getName())) { + SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd(); + for( ; SCI != SCE; ++SCI) { + if (SCI->ItinClassDef == ItinDef) { + ProcModel.ItinDefList[SCI->Index] = ItinData; + break; + } + } + if (SCI == SCE) { DEBUG(dbgs() << ProcModel.ItinsDef->getName() - << " has unused itinerary class " << ItinDef->getName() << '\n'); - continue; + << " missing class for itinerary " << ItinDef->getName() << '\n'); } - assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass"); - unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName()); - assert(Idx <= NumItineraryClasses && "bad ItinClass index"); - ProcModel.ItinDefList[Idx] = ItinData; } // Check for missing itinerary entries. assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec"); @@ -839,13 +823,17 @@ void CodeGenSchedModels::collectProcItinRW() { /// Infer new classes from existing classes. In the process, this may create new /// SchedWrites from sequences of existing SchedWrites. void CodeGenSchedModels::inferSchedClasses() { + DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n"); + // Visit all existing classes and newly created classes. for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) { + assert(SchedClasses[Idx].Index == Idx && "bad SCIdx"); + if (SchedClasses[Idx].ItinClassDef) inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx); - else if (!SchedClasses[Idx].InstRWs.empty()) + if (!SchedClasses[Idx].InstRWs.empty()) inferFromInstRWs(Idx); - else { + if (!SchedClasses[Idx].Writes.empty()) { inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads, Idx, SchedClasses[Idx].ProcIndices); } @@ -1295,8 +1283,8 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end()); CodeGenSchedTransition SCTrans; SCTrans.ToClassIdx = - SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant, - ProcIndices); + SchedModels.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant, + OperReadsVariant, ProcIndices); SCTrans.ProcIndices = ProcIndices; // The final PredTerm is unique set of predicates guarding the transition. RecVec Preds; @@ -1642,7 +1630,7 @@ void CodeGenSchedRW::dump() const { } void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const { - dbgs() << "SCHEDCLASS " << Name << '\n' + dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n' << " Writes: "; for (unsigned i = 0, N = Writes.size(); i < N; ++i) { SchedModels->getSchedWrite(Writes[i]).dump(); diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 78f115e..e5b9118 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -125,6 +125,7 @@ struct CodeGenSchedTransition { /// itinerary class. Each inherits the processor index from the ItinRW record /// that mapped the itinerary class to the variant Writes or Reads. struct CodeGenSchedClass { + unsigned Index; std::string Name; Record *ItinClassDef; @@ -141,12 +142,16 @@ struct CodeGenSchedClass { // off to join another inferred class. RecVec InstRWs; - CodeGenSchedClass(): ItinClassDef(0) {} - CodeGenSchedClass(Record *rec): ItinClassDef(rec) { - Name = rec->getName(); - ProcIndices.push_back(0); + CodeGenSchedClass(): Index(0), ItinClassDef(0) {} + + bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) { + return ItinClassDef == IC && Writes == W && Reads == R; } + // Is this class generated from a variants if existing classes? Instructions + // are never mapped directly to inferred scheduling classes. + bool isInferred() const { return !ItinClassDef; } + #ifndef NDEBUG void dump(const CodeGenSchedModels *SchedModels) const; #endif @@ -189,11 +194,16 @@ struct CodeGenProcModel { // Per-operand machine model resources associated with this processor. RecVec ProcResourceDefs; + RecVec ProcResGroupDefs; CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef, Record *IDef) : Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {} + bool hasItineraries() const { + return !ItinsDef->getValueAsListOfDefs("IID").empty(); + } + bool hasInstrSchedModel() const { return !WriteResDefs.empty() || !ItinRWDefs.empty(); } @@ -227,24 +237,11 @@ class CodeGenSchedModels { // List of unique SchedClasses. std::vector<CodeGenSchedClass> SchedClasses; - // Map SchedClass name to itinerary index. - // These are either explicit itinerary classes or classes implied by - // instruction definitions with SchedReadWrite lists. - StringMap<unsigned> SchedClassIdxMap; - - // SchedClass indices 1 up to and including NumItineraryClasses identify - // itinerary classes that are explicitly used for this target's instruction - // definitions. NoItinerary always has index 0 regardless of whether it is - // explicitly referenced. - // - // Any implied SchedClass has an index greater than NumItineraryClasses. - unsigned NumItineraryClasses; - // Any inferred SchedClass has an index greater than NumInstrSchedClassses. unsigned NumInstrSchedClasses; - // Map Instruction to SchedClass index. Only for Instructions mentioned in - // InstRW records. + // Map each instruction to its unique SchedClass index considering the + // combination of it's itinerary class, SchedRW list, and InstRW records. typedef DenseMap<Record*, unsigned> InstClassMapTy; InstClassMapTy InstrClassMap; @@ -280,6 +277,9 @@ public: ProcIter procModelBegin() const { return ProcModels.begin(); } ProcIter procModelEnd() const { return ProcModels.end(); } + // Return true if any processors have itineraries. + bool hasItineraries() const; + // Get a SchedWrite from its index. const CodeGenSchedRW &getSchedWrite(unsigned Idx) const { assert(Idx < SchedWrites.size() && "bad SchedWrite index"); @@ -311,16 +311,6 @@ public: // Return true if the given write record is referenced by a ReadAdvance. bool hasReadOfWrite(Record *WriteDef) const; - // Check if any instructions are assigned to an explicit itinerary class other - // than NoItinerary. - bool hasItineraryClasses() const { return NumItineraryClasses > 0; } - - // Return the number of itinerary classes in use by this target's instruction - // descriptions, not including "NoItinerary". - unsigned numItineraryClasses() const { - return NumItineraryClasses; - } - // Get a SchedClass from its index. CodeGenSchedClass &getSchedClass(unsigned Idx) { assert(Idx < SchedClasses.size() && "bad SchedClass index"); @@ -336,28 +326,26 @@ public: // for NoItinerary. unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const; - unsigned getSchedClassIdx(const RecVec &RWDefs) const; - - unsigned getSchedClassIdxForItin(const Record *ItinDef) { - return SchedClassIdxMap[ItinDef->getName()]; - } - typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter; SchedClassIter schedClassBegin() const { return SchedClasses.begin(); } SchedClassIter schedClassEnd() const { return SchedClasses.end(); } + unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; } + void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const; void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const; void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const; void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead, const CodeGenProcModel &ProcModel) const; - unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads, - const IdxVec &ProcIndices); + unsigned addSchedClass(Record *ItinDef, const IdxVec &OperWrites, + const IdxVec &OperReads, const IdxVec &ProcIndices); unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead); - unsigned findSchedClassIdx(const IdxVec &Writes, const IdxVec &Reads) const; + unsigned findSchedClassIdx(Record *ItinClassDef, + const IdxVec &Writes, + const IdxVec &Reads) const; Record *findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM) const; @@ -375,7 +363,8 @@ private: void collectSchedClasses(); - std::string createSchedClassName(const IdxVec &OperWrites, + std::string createSchedClassName(Record *ItinClassDef, + const IdxVec &OperWrites, const IdxVec &OperReads); std::string createSchedClassName(const RecVec &InstDefs); void createInstRWClass(Record *InstRWDef); diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 299a5af..5fb811e 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -447,17 +447,15 @@ EmitStageAndOperandCycleData(raw_ostream &OS, // If this processor defines no itineraries, then leave the itinerary list // empty. std::vector<InstrItinerary> &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 @@ -869,27 +867,8 @@ 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.ModelName - << " 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; for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); @@ -907,6 +886,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<MCWriteProcResEntry> WriteProcResources; std::vector<MCWriteLatencyEntry> WriteLatencies; @@ -924,7 +920,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; @@ -1140,7 +1137,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 @@ -1197,7 +1194,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraryClasses()) + if (SchedModels.hasItineraries()) OS << " " << PI->ItinsDef->getName() << ");\n"; else OS << " 0); // No Itinerary\n"; @@ -1254,7 +1251,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { << "#define DBGFIELD(x)\n" << "#endif\n"; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { std::vector<std::vector<InstrItinerary> > ProcItinLists; // Emit the stage data EmitStageAndOperandCycleData(OS, ProcItinLists); @@ -1295,7 +1292,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"; @@ -1342,13 +1339,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"; @@ -1454,7 +1446,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << '\n'; OS.indent(22); OS << Target << "Stages, " << Target << "OperandCycles, " @@ -1511,7 +1503,7 @@ 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"; @@ -1535,7 +1527,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << Target << "WriteLatencyTable, " << Target << "ReadAdvanceTable, "; OS << '\n'; OS.indent(22); - if (SchedModels.hasItineraryClasses()) { + if (SchedModels.hasItineraries()) { OS << Target << "Stages, " << Target << "OperandCycles, " << Target << "ForwardingPaths, "; |