diff options
-rw-r--r-- | include/llvm/Target/TargetInstrItineraries.h | 44 | ||||
-rw-r--r-- | include/llvm/Target/TargetSchedule.td | 4 | ||||
-rw-r--r-- | lib/CodeGen/ExactHazardRecognizer.cpp | 11 | ||||
-rw-r--r-- | utils/TableGen/SubtargetEmitter.cpp | 141 | ||||
-rw-r--r-- | utils/TableGen/SubtargetEmitter.h | 8 |
5 files changed, 140 insertions, 68 deletions
diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h index 237ca4ef2a..9ba9cb61c5 100644 --- a/include/llvm/Target/TargetInstrItineraries.h +++ b/include/llvm/Target/TargetInstrItineraries.h @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This file describes the structures used for instruction itineraries and -// stages. This is used by schedulers to determine instruction stages and -// latencies. +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. // //===----------------------------------------------------------------------===// @@ -71,46 +71,50 @@ struct InstrStage { //===----------------------------------------------------------------------===// -/// Instruction itinerary - An itinerary represents a sequential series of steps -/// required to complete an instruction. Itineraries are represented as -/// sequences of instruction stages. +/// Instruction itinerary - An itinerary represents the scheduling +/// information for an instruction. This includes a set of stages +/// occupies by the instruction, and the pipeline cycle in which +/// operands are read and written. /// struct InstrItinerary { - unsigned First; ///< Index of first stage in itinerary - unsigned Last; ///< Index of last + 1 stage in itinerary + unsigned FirstStage; ///< Index of first stage in itinerary + unsigned LastStage; ///< Index of last + 1 stage in itinerary + unsigned FirstOperandCycle; ///< Index of first operand rd/wr + unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr }; - //===----------------------------------------------------------------------===// /// Instruction itinerary Data - Itinerary data supplied by a subtarget to be /// used by a target. /// struct InstrItineraryData { const InstrStage *Stages; ///< Array of stages selected + const unsigned *OperandCycles; ///< Array of operand cycles selected const InstrItinerary *Itineratries; ///< Array of itineraries selected /// Ctors. /// - InstrItineraryData() : Stages(0), Itineratries(0) {} - InstrItineraryData(const InstrStage *S, const InstrItinerary *I) - : Stages(S), Itineratries(I) {} + InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {} + InstrItineraryData(const InstrStage *S, const unsigned *OS, + const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Itineratries(I) {} /// isEmpty - Returns true if there are no itineraries. /// bool isEmpty() const { return Itineratries == 0; } - /// begin - Return the first stage of the itinerary. + /// beginStage - Return the first stage of the itinerary. /// - const InstrStage *begin(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineratries[ItinClassIndx].First; + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// end - Return the last+1 stage of the itinerary. + /// endStage - Return the last+1 stage of the itinerary. /// - const InstrStage *end(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineratries[ItinClassIndx].Last; + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].LastStage; return Stages + StageIdx; } @@ -129,8 +133,8 @@ struct InstrItineraryData { // first stage and that all outputs are produced at the end of the // latest completing last stage. unsigned Latency = 0, StartCycle = 0; - for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx); - IS != E; ++IS) { + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { Latency = std::max(Latency, StartCycle + IS->getCycles()); StartCycle += IS->getNextCycles(); } diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 4940e8b82b..b3f566a3c3 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -62,9 +62,11 @@ def NoItinerary : InstrItinClass; // Instruction itinerary data - These values provide a runtime map of an // instruction itinerary class (name) to it's itinerary data. // -class InstrItinData<InstrItinClass Class, list<InstrStage> stages> { +class InstrItinData<InstrItinClass Class, list<InstrStage> stages, + list<int> operandcycles = []> { InstrItinClass TheClass = Class; list<InstrStage> Stages = stages; + list<int> OperandCycles = operandcycles; } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/ExactHazardRecognizer.cpp b/lib/CodeGen/ExactHazardRecognizer.cpp index 8bac08a4a0..33ee233dac 100644 --- a/lib/CodeGen/ExactHazardRecognizer.cpp +++ b/lib/CodeGen/ExactHazardRecognizer.cpp @@ -33,7 +33,8 @@ ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData for (unsigned idx = 0; ; ++idx) { // If the begin stage of an itinerary has 0 cycles and units, // then we have reached the end of the itineraries. - const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); + const InstrStage *IS = ItinData.beginStage(idx); + const InstrStage *E = ItinData.endStage(idx); if ((IS->getCycles() == 0) && (IS->getUnits() == 0)) break; @@ -87,8 +88,8 @@ ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU // Use the itinerary for the underlying instruction to check for // free FU's in the scoreboard at the appropriate future cycles. unsigned idx = SU->getInstr()->getDesc().getSchedClass(); - for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); - IS != E; ++IS) { + for (const InstrStage *IS = ItinData.beginStage(idx), + *E = ItinData.endStage(idx); IS != E; ++IS) { // We must find one of the stage's units free for every cycle the // stage is occupied. FIXME it would be more accurate to find the // same unit free in all the cycles. @@ -119,8 +120,8 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) { // Use the itinerary for the underlying instruction to reserve FU's // in the scoreboard at the appropriate future cycles. unsigned idx = SU->getInstr()->getDesc().getSchedClass(); - for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); - IS != E; ++IS) { + for (const InstrStage *IS = ItinData.beginStage(idx), + *E = ItinData.endStage(idx); IS != E; ++IS) { // We must reserve one of the stage's units for every cycle the // stage is occupied. FIXME it would be more accurate to reserve // the same unit free in all the cycles. diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 4a0bacd19c..9760b171dd 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -199,12 +199,13 @@ unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS, } // -// FormItineraryString - Compose a string containing the data initialization -// for the specified itinerary. N is the number of stages. +// FormItineraryStageString - Compose a string containing the stage +// data initialization for the specified itinerary. N is the number +// of stages. // -void SubtargetEmitter::FormItineraryString(Record *ItinData, - std::string &ItinString, - unsigned &NStages) { +void SubtargetEmitter::FormItineraryStageString(Record *ItinData, + std::string &ItinString, + unsigned &NStages) { // Get states list const std::vector<Record*> &StageList = ItinData->getValueAsListOfDefs("Stages"); @@ -239,10 +240,32 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData, } // -// EmitStageData - Generate unique itinerary stages. Record itineraries for -// processors. +// FormItineraryOperandCycleString - Compose a string containing the +// operand cycle initialization for the specified itinerary. N is the +// number of operands that has cycles specified. // -void SubtargetEmitter::EmitStageData(raw_ostream &OS, +void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, + std::string &ItinString, unsigned &NOperandCycles) { + // Get operand cycle list + const std::vector<int64_t> &OperandCycleList = + ItinData->getValueAsListOfInts("OperandCycles"); + + // For each operand cycle + unsigned N = NOperandCycles = OperandCycleList.size(); + for (unsigned i = 0; i < N;) { + // Next operand cycle + const int OCycle = OperandCycleList[i]; + + ItinString += " " + itostr(OCycle); + if (++i < N) ItinString += ", "; + } +} + +// +// EmitStageAndOperandCycleData - Generate unique itinerary stages and +// operand cycle tables. Record itineraries for processors. +// +void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses, std::map<std::string, unsigned> &ItinClassesMap, std::vector<std::vector<InstrItinerary> > &ProcList) { @@ -254,12 +277,16 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS, if (ProcItinList.size() < 2) return; // Begin stages table - OS << "static const llvm::InstrStage Stages[] = {\n" - " { 0, 0, 0 }, // No itinerary\n"; + std::string StageTable = "static const llvm::InstrStage Stages[] = {\n"; + StageTable += " { 0, 0, 0 }, // No itinerary\n"; - unsigned StageCount = 1; - unsigned ItinEnum = 1; - std::map<std::string, unsigned> ItinMap; + // Begin operand cycle table + std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; + OperandCycleTable += " 0, // No itinerary\n"; + + unsigned StageCount = 1, OperandCycleCount = 1; + unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1; + std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap; for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { // Next record Record *Proc = ProcItinList[i]; @@ -283,29 +310,53 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS, Record *ItinData = ItinDataList[j]; // Get string and stage count - std::string ItinString; + std::string ItinStageString; unsigned NStages; - FormItineraryString(ItinData, ItinString, NStages); - - // Check to see if it already exists - unsigned Find = ItinMap[ItinString]; + FormItineraryStageString(ItinData, ItinStageString, NStages); + + // Get string and operand cycle count + std::string ItinOperandCycleString; + unsigned NOperandCycles; + FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, + NOperandCycles); + + // Check to see if stage already exists and create if it doesn't + unsigned FindStage = 0; + if (NStages > 0) { + FindStage = ItinStageMap[ItinStageString]; + if (FindStage == 0) { + // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index + StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n"; + // Record Itin class number. + ItinStageMap[ItinStageString] = FindStage = StageCount; + StageCount += NStages; + ItinStageEnum++; + } + } - // If new itinerary - if (Find == 0) { - // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index - OS << ItinString << ", // " << ItinEnum << "\n"; - // Record Itin class number. - ItinMap[ItinString] = Find = StageCount; - StageCount += NStages; - ItinEnum++; + // Check to see if operand cycle already exists and create if it doesn't + unsigned FindOperandCycle = 0; + if (NOperandCycles > 0) { + FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString]; + if (FindOperandCycle == 0) { + // Emit as cycle, // index + OperandCycleTable += ItinOperandCycleString + ", // " + + itostr(ItinOperandCycleEnum) + "\n"; + // Record Itin class number. + ItinOperandCycleMap[ItinOperandCycleString] = + FindOperandCycle = OperandCycleCount; + OperandCycleCount += NOperandCycles; + ItinOperandCycleEnum++; + } } // Set up itinerary as location and location + stage count - InstrItinerary Intinerary = { Find, Find + NStages }; + InstrItinerary Intinerary = { FindStage, FindStage + NStages, + FindOperandCycle, FindOperandCycle + NOperandCycles}; // Locate where to inject into processor itinerary table const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); - Find = ItinClassesMap[Name]; + unsigned Find = ItinClassesMap[Name]; // Inject - empty slots will be 0, 0 ItinList[Find] = Intinerary; @@ -316,13 +367,21 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS, } // Closing stage - OS << " { 0, 0, 0 } // End itinerary\n"; - // End stages table - OS << "};\n"; + StageTable += " { 0, 0, 0 } // End itinerary\n"; + StageTable += "};\n"; + + // Closing operand cycles + OperandCycleTable += " 0 // End itinerary\n"; + OperandCycleTable += "};\n"; + + // Emit tables. + OS << StageTable; + OS << OperandCycleTable; - // Emit size of table + // Emit size of tables OS<<"\nenum {\n"; - OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n"; + OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n"; + OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n"; OS<<"};\n"; } @@ -357,11 +416,15 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS, for (unsigned j = 0, M = ItinList.size(); j < M;) { InstrItinerary &Intinerary = ItinList[j]; - // Emit in the form of { first, last } // index - if (Intinerary.First == 0) { - OS << " { 0, 0 }"; + // Emit in the form of + // { firstStage, lastStage, firstCycle, lastCycle } // index + if (Intinerary.FirstStage == 0) { + OS << " { 0, 0, 0, 0 }"; } else { - OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }"; + OS << " { " << Intinerary.FirstStage << ", " << + Intinerary.LastStage << ", " << + Intinerary.FirstOperandCycle << ", " << + Intinerary.LastOperandCycle << " }"; } // If more in list add comma @@ -435,7 +498,7 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) { if (HasItineraries) { // Emit the stage data - EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList); + EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList); // Emit the processor itinerary data EmitProcessorData(OS, ProcList); // Emit the processor lookup data @@ -482,7 +545,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { OS << "\n" << " InstrItinerary *Itinerary = (InstrItinerary *)" << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" - << " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; + << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n"; } OS << " return Features.getCPU();\n" diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index f44278cc15..1d7088fd39 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -34,9 +34,11 @@ class SubtargetEmitter : public TableGenBackend { void CPUKeyValues(raw_ostream &OS); unsigned CollectAllItinClasses(raw_ostream &OS, std::map<std::string, unsigned> &ItinClassesMap); - void FormItineraryString(Record *ItinData, std::string &ItinString, - unsigned &NStages); - void EmitStageData(raw_ostream &OS, unsigned NItinClasses, + void FormItineraryStageString(Record *ItinData, std::string &ItinString, + unsigned &NStages); + void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, + unsigned &NOperandCycles); + void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses, std::map<std::string, unsigned> &ItinClassesMap, std::vector<std::vector<InstrItinerary> > &ProcList); void EmitProcessorData(raw_ostream &OS, |