Extend the instruction itinerary model to include the ability to indicate the def and use cycle for each operand. This additional information is optional, so existing itineraries do not need to be changed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79247 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Goodwin 2009-08-17 16:02:57 +00:00
parent 8f4b1ec02b
commit fac8541dd4
5 changed files with 139 additions and 67 deletions

View File

@ -7,9 +7,9 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file describes the structures used for instruction itineraries and // This file describes the structures used for instruction
// stages. This is used by schedulers to determine instruction stages and // itineraries, stages, and operand reads/writes. This is used by
// latencies. // schedulers to determine instruction stages and latencies.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -71,46 +71,50 @@ struct InstrStage {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Instruction itinerary - An itinerary represents a sequential series of steps /// Instruction itinerary - An itinerary represents the scheduling
/// required to complete an instruction. Itineraries are represented as /// information for an instruction. This includes a set of stages
/// sequences of instruction stages. /// occupies by the instruction, and the pipeline cycle in which
/// operands are read and written.
/// ///
struct InstrItinerary { struct InstrItinerary {
unsigned First; ///< Index of first stage in itinerary unsigned FirstStage; ///< Index of first stage in itinerary
unsigned Last; ///< Index of last + 1 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 /// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
/// used by a target. /// used by a target.
/// ///
struct InstrItineraryData { struct InstrItineraryData {
const InstrStage *Stages; ///< Array of stages selected const InstrStage *Stages; ///< Array of stages selected
const unsigned *OperandCycles; ///< Array of operand cycles selected
const InstrItinerary *Itineratries; ///< Array of itineraries selected const InstrItinerary *Itineratries; ///< Array of itineraries selected
/// Ctors. /// Ctors.
/// ///
InstrItineraryData() : Stages(0), Itineratries(0) {} InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {}
InstrItineraryData(const InstrStage *S, const InstrItinerary *I) InstrItineraryData(const InstrStage *S, const unsigned *OS,
: Stages(S), Itineratries(I) {} const InstrItinerary *I)
: Stages(S), OperandCycles(OS), Itineratries(I) {}
/// isEmpty - Returns true if there are no itineraries. /// isEmpty - Returns true if there are no itineraries.
/// ///
bool isEmpty() const { return Itineratries == 0; } 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 { const InstrStage *beginStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineratries[ItinClassIndx].First; unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage;
return Stages + StageIdx; 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 { const InstrStage *endStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineratries[ItinClassIndx].Last; unsigned StageIdx = Itineratries[ItinClassIndx].LastStage;
return Stages + StageIdx; return Stages + StageIdx;
} }
@ -129,8 +133,8 @@ struct InstrItineraryData {
// first stage and that all outputs are produced at the end of the // first stage and that all outputs are produced at the end of the
// latest completing last stage. // latest completing last stage.
unsigned Latency = 0, StartCycle = 0; unsigned Latency = 0, StartCycle = 0;
for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx); for (const InstrStage *IS = beginStage(ItinClassIndx),
IS != E; ++IS) { *E = endStage(ItinClassIndx); IS != E; ++IS) {
Latency = std::max(Latency, StartCycle + IS->getCycles()); Latency = std::max(Latency, StartCycle + IS->getCycles());
StartCycle += IS->getNextCycles(); StartCycle += IS->getNextCycles();
} }

View File

@ -62,9 +62,11 @@ def NoItinerary : InstrItinClass;
// Instruction itinerary data - These values provide a runtime map of an // Instruction itinerary data - These values provide a runtime map of an
// instruction itinerary class (name) to it's itinerary data. // 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; InstrItinClass TheClass = Class;
list<InstrStage> Stages = stages; list<InstrStage> Stages = stages;
list<int> OperandCycles = operandcycles;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -33,7 +33,8 @@ ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData
for (unsigned idx = 0; ; ++idx) { for (unsigned idx = 0; ; ++idx) {
// If the begin stage of an itinerary has 0 cycles and units, // If the begin stage of an itinerary has 0 cycles and units,
// then we have reached the end of the itineraries. // 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)) if ((IS->getCycles() == 0) && (IS->getUnits() == 0))
break; break;
@ -87,8 +88,8 @@ ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU
// Use the itinerary for the underlying instruction to check for // Use the itinerary for the underlying instruction to check for
// free FU's in the scoreboard at the appropriate future cycles. // free FU's in the scoreboard at the appropriate future cycles.
unsigned idx = SU->getInstr()->getDesc().getSchedClass(); unsigned idx = SU->getInstr()->getDesc().getSchedClass();
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); for (const InstrStage *IS = ItinData.beginStage(idx),
IS != E; ++IS) { *E = ItinData.endStage(idx); IS != E; ++IS) {
// We must find one of the stage's units free for every cycle the // 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 // stage is occupied. FIXME it would be more accurate to find the
// same unit free in all the cycles. // 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 // Use the itinerary for the underlying instruction to reserve FU's
// in the scoreboard at the appropriate future cycles. // in the scoreboard at the appropriate future cycles.
unsigned idx = SU->getInstr()->getDesc().getSchedClass(); unsigned idx = SU->getInstr()->getDesc().getSchedClass();
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); for (const InstrStage *IS = ItinData.beginStage(idx),
IS != E; ++IS) { *E = ItinData.endStage(idx); IS != E; ++IS) {
// We must reserve one of the stage's units for every cycle the // We must reserve one of the stage's units for every cycle the
// stage is occupied. FIXME it would be more accurate to reserve // stage is occupied. FIXME it would be more accurate to reserve
// the same unit free in all the cycles. // the same unit free in all the cycles.

View File

@ -199,10 +199,11 @@ unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
} }
// //
// FormItineraryString - Compose a string containing the data initialization // FormItineraryStageString - Compose a string containing the stage
// for the specified itinerary. N is the number of stages. // data initialization for the specified itinerary. N is the number
// of stages.
// //
void SubtargetEmitter::FormItineraryString(Record *ItinData, void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
std::string &ItinString, std::string &ItinString,
unsigned &NStages) { unsigned &NStages) {
// Get states list // Get states list
@ -239,10 +240,32 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
} }
// //
// EmitStageData - Generate unique itinerary stages. Record itineraries for // FormItineraryOperandCycleString - Compose a string containing the
// processors. // 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, unsigned NItinClasses,
std::map<std::string, unsigned> &ItinClassesMap, std::map<std::string, unsigned> &ItinClassesMap,
std::vector<std::vector<InstrItinerary> > &ProcList) { std::vector<std::vector<InstrItinerary> > &ProcList) {
@ -254,12 +277,16 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
if (ProcItinList.size() < 2) return; if (ProcItinList.size() < 2) return;
// Begin stages table // Begin stages table
OS << "static const llvm::InstrStage Stages[] = {\n" std::string StageTable = "static const llvm::InstrStage Stages[] = {\n";
" { 0, 0, 0 }, // No itinerary\n"; StageTable += " { 0, 0, 0 }, // No itinerary\n";
unsigned StageCount = 1; // Begin operand cycle table
unsigned ItinEnum = 1; std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
std::map<std::string, unsigned> ItinMap; 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++) { for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
// Next record // Next record
Record *Proc = ProcItinList[i]; Record *Proc = ProcItinList[i];
@ -283,29 +310,53 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
Record *ItinData = ItinDataList[j]; Record *ItinData = ItinDataList[j];
// Get string and stage count // Get string and stage count
std::string ItinString; std::string ItinStageString;
unsigned NStages; unsigned NStages;
FormItineraryString(ItinData, ItinString, NStages); FormItineraryStageString(ItinData, ItinStageString, NStages);
// Check to see if it already exists // Get string and operand cycle count
unsigned Find = ItinMap[ItinString]; std::string ItinOperandCycleString;
unsigned NOperandCycles;
FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
NOperandCycles);
// If new itinerary // Check to see if stage already exists and create if it doesn't
if (Find == 0) { unsigned FindStage = 0;
if (NStages > 0) {
FindStage = ItinStageMap[ItinStageString];
if (FindStage == 0) {
// Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
OS << ItinString << ", // " << ItinEnum << "\n"; StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
// Record Itin class number. // Record Itin class number.
ItinMap[ItinString] = Find = StageCount; ItinStageMap[ItinStageString] = FindStage = StageCount;
StageCount += NStages; StageCount += NStages;
ItinEnum++; ItinStageEnum++;
}
}
// 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 // 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 // Locate where to inject into processor itinerary table
const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
Find = ItinClassesMap[Name]; unsigned Find = ItinClassesMap[Name];
// Inject - empty slots will be 0, 0 // Inject - empty slots will be 0, 0
ItinList[Find] = Intinerary; ItinList[Find] = Intinerary;
@ -316,13 +367,21 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
} }
// Closing stage // Closing stage
OS << " { 0, 0, 0 } // End itinerary\n"; StageTable += " { 0, 0, 0 } // End itinerary\n";
// End stages table StageTable += "};\n";
OS << "};\n";
// Emit size of table // Closing operand cycles
OperandCycleTable += " 0 // End itinerary\n";
OperandCycleTable += "};\n";
// Emit tables.
OS << StageTable;
OS << OperandCycleTable;
// Emit size of tables
OS<<"\nenum {\n"; 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"; OS<<"};\n";
} }
@ -357,11 +416,15 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
for (unsigned j = 0, M = ItinList.size(); j < M;) { for (unsigned j = 0, M = ItinList.size(); j < M;) {
InstrItinerary &Intinerary = ItinList[j]; InstrItinerary &Intinerary = ItinList[j];
// Emit in the form of { first, last } // index // Emit in the form of
if (Intinerary.First == 0) { // { firstStage, lastStage, firstCycle, lastCycle } // index
OS << " { 0, 0 }"; if (Intinerary.FirstStage == 0) {
OS << " { 0, 0, 0, 0 }";
} else { } else {
OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }"; OS << " { " << Intinerary.FirstStage << ", " <<
Intinerary.LastStage << ", " <<
Intinerary.FirstOperandCycle << ", " <<
Intinerary.LastOperandCycle << " }";
} }
// If more in list add comma // If more in list add comma
@ -435,7 +498,7 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) {
if (HasItineraries) { if (HasItineraries) {
// Emit the stage data // Emit the stage data
EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList); EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
// Emit the processor itinerary data // Emit the processor itinerary data
EmitProcessorData(OS, ProcList); EmitProcessorData(OS, ProcList);
// Emit the processor lookup data // Emit the processor lookup data
@ -482,7 +545,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
OS << "\n" OS << "\n"
<< " InstrItinerary *Itinerary = (InstrItinerary *)" << " InstrItinerary *Itinerary = (InstrItinerary *)"
<< "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
<< " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
} }
OS << " return Features.getCPU();\n" OS << " return Features.getCPU();\n"

View File

@ -34,9 +34,11 @@ class SubtargetEmitter : public TableGenBackend {
void CPUKeyValues(raw_ostream &OS); void CPUKeyValues(raw_ostream &OS);
unsigned CollectAllItinClasses(raw_ostream &OS, unsigned CollectAllItinClasses(raw_ostream &OS,
std::map<std::string, unsigned> &ItinClassesMap); std::map<std::string, unsigned> &ItinClassesMap);
void FormItineraryString(Record *ItinData, std::string &ItinString, void FormItineraryStageString(Record *ItinData, std::string &ItinString,
unsigned &NStages); unsigned &NStages);
void EmitStageData(raw_ostream &OS, unsigned NItinClasses, void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
unsigned &NOperandCycles);
void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
std::map<std::string, unsigned> &ItinClassesMap, std::map<std::string, unsigned> &ItinClassesMap,
std::vector<std::vector<InstrItinerary> > &ProcList); std::vector<std::vector<InstrItinerary> > &ProcList);
void EmitProcessorData(raw_ostream &OS, void EmitProcessorData(raw_ostream &OS,