aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetInstrItineraries.h44
-rw-r--r--include/llvm/Target/TargetSchedule.td4
-rw-r--r--lib/CodeGen/ExactHazardRecognizer.cpp11
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp141
-rw-r--r--utils/TableGen/SubtargetEmitter.h8
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,