llvm.org GIT mirror llvm / fac8541
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 David Goodwin 10 years ago
5 changed file(s) with 144 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
66 //
77 //===----------------------------------------------------------------------===//
88 //
9 // This file describes the structures used for instruction itineraries and
10 // stages. This is used by schedulers to determine instruction stages and
11 // latencies.
9 // This file describes the structures used for instruction
10 // itineraries, stages, and operand reads/writes. This is used by
11 // schedulers to determine instruction stages and latencies.
1212 //
1313 //===----------------------------------------------------------------------===//
1414
7070
7171
7272 //===----------------------------------------------------------------------===//
73 /// Instruction itinerary - An itinerary represents a sequential series of steps
74 /// required to complete an instruction. Itineraries are represented as
75 /// sequences of instruction stages.
73 /// Instruction itinerary - An itinerary represents the scheduling
74 /// information for an instruction. This includes a set of stages
75 /// occupies by the instruction, and the pipeline cycle in which
76 /// operands are read and written.
7677 ///
7778 struct InstrItinerary {
78 unsigned First; ///< Index of first stage in itinerary
79 unsigned Last; ///< Index of last + 1 stage in itinerary
79 unsigned FirstStage; ///< Index of first stage in itinerary
80 unsigned LastStage; ///< Index of last + 1 stage in itinerary
81 unsigned FirstOperandCycle; ///< Index of first operand rd/wr
82 unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr
8083 };
81
8284
8385
8486 //===----------------------------------------------------------------------===//
8789 ///
8890 struct InstrItineraryData {
8991 const InstrStage *Stages; ///< Array of stages selected
92 const unsigned *OperandCycles; ///< Array of operand cycles selected
9093 const InstrItinerary *Itineratries; ///< Array of itineraries selected
9194
9295 /// Ctors.
9396 ///
94 InstrItineraryData() : Stages(0), Itineratries(0) {}
95 InstrItineraryData(const InstrStage *S, const InstrItinerary *I)
96 : Stages(S), Itineratries(I) {}
97 InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {}
98 InstrItineraryData(const InstrStage *S, const unsigned *OS,
99 const InstrItinerary *I)
100 : Stages(S), OperandCycles(OS), Itineratries(I) {}
97101
98102 /// isEmpty - Returns true if there are no itineraries.
99103 ///
100104 bool isEmpty() const { return Itineratries == 0; }
101105
102 /// begin - Return the first stage of the itinerary.
106 /// beginStage - Return the first stage of the itinerary.
103107 ///
104 const InstrStage *begin(unsigned ItinClassIndx) const {
105 unsigned StageIdx = Itineratries[ItinClassIndx].First;
108 const InstrStage *beginStage(unsigned ItinClassIndx) const {
109 unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage;
106110 return Stages + StageIdx;
107111 }
108112
109 /// end - Return the last+1 stage of the itinerary.
113 /// endStage - Return the last+1 stage of the itinerary.
110114 ///
111 const InstrStage *end(unsigned ItinClassIndx) const {
112 unsigned StageIdx = Itineratries[ItinClassIndx].Last;
115 const InstrStage *endStage(unsigned ItinClassIndx) const {
116 unsigned StageIdx = Itineratries[ItinClassIndx].LastStage;
113117 return Stages + StageIdx;
114118 }
115119
128132 // first stage and that all outputs are produced at the end of the
129133 // latest completing last stage.
130134 unsigned Latency = 0, StartCycle = 0;
131 for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx);
132 IS != E; ++IS) {
135 for (const InstrStage *IS = beginStage(ItinClassIndx),
136 *E = endStage(ItinClassIndx); IS != E; ++IS) {
133137 Latency = std::max(Latency, StartCycle + IS->getCycles());
134138 StartCycle += IS->getNextCycles();
135139 }
6161 // Instruction itinerary data - These values provide a runtime map of an
6262 // instruction itinerary class (name) to it's itinerary data.
6363 //
64 class InstrItinData stages> {
64 class InstrItinData stages,
65 list operandcycles = []> {
6566 InstrItinClass TheClass = Class;
6667 list Stages = stages;
68 list OperandCycles = operandcycles;
6769 }
6870
6971 //===----------------------------------------------------------------------===//
3232 for (unsigned idx = 0; ; ++idx) {
3333 // If the begin stage of an itinerary has 0 cycles and units,
3434 // then we have reached the end of the itineraries.
35 const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
35 const InstrStage *IS = ItinData.beginStage(idx);
36 const InstrStage *E = ItinData.endStage(idx);
3637 if ((IS->getCycles() == 0) && (IS->getUnits() == 0))
3738 break;
3839
8687 // Use the itinerary for the underlying instruction to check for
8788 // free FU's in the scoreboard at the appropriate future cycles.
8889 unsigned idx = SU->getInstr()->getDesc().getSchedClass();
89 for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
90 IS != E; ++IS) {
90 for (const InstrStage *IS = ItinData.beginStage(idx),
91 *E = ItinData.endStage(idx); IS != E; ++IS) {
9192 // We must find one of the stage's units free for every cycle the
9293 // stage is occupied. FIXME it would be more accurate to find the
9394 // same unit free in all the cycles.
118119 // Use the itinerary for the underlying instruction to reserve FU's
119120 // in the scoreboard at the appropriate future cycles.
120121 unsigned idx = SU->getInstr()->getDesc().getSchedClass();
121 for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
122 IS != E; ++IS) {
122 for (const InstrStage *IS = ItinData.beginStage(idx),
123 *E = ItinData.endStage(idx); IS != E; ++IS) {
123124 // We must reserve one of the stage's units for every cycle the
124125 // stage is occupied. FIXME it would be more accurate to reserve
125126 // the same unit free in all the cycles.
198198 }
199199
200200 //
201 // FormItineraryString - Compose a string containing the data initialization
202 // for the specified itinerary. N is the number of stages.
203 //
204 void SubtargetEmitter::FormItineraryString(Record *ItinData,
205 std::string &ItinString,
206 unsigned &NStages) {
201 // FormItineraryStageString - Compose a string containing the stage
202 // data initialization for the specified itinerary. N is the number
203 // of stages.
204 //
205 void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
206 std::string &ItinString,
207 unsigned &NStages) {
207208 // Get states list
208209 const std::vector &StageList =
209210 ItinData->getValueAsListOfDefs("Stages");
238239 }
239240
240241 //
241 // EmitStageData - Generate unique itinerary stages. Record itineraries for
242 // processors.
243 //
244 void SubtargetEmitter::EmitStageData(raw_ostream &OS,
242 // FormItineraryOperandCycleString - Compose a string containing the
243 // operand cycle initialization for the specified itinerary. N is the
244 // number of operands that has cycles specified.
245 //
246 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
247 std::string &ItinString, unsigned &NOperandCycles) {
248 // Get operand cycle list
249 const std::vector &OperandCycleList =
250 ItinData->getValueAsListOfInts("OperandCycles");
251
252 // For each operand cycle
253 unsigned N = NOperandCycles = OperandCycleList.size();
254 for (unsigned i = 0; i < N;) {
255 // Next operand cycle
256 const int OCycle = OperandCycleList[i];
257
258 ItinString += " " + itostr(OCycle);
259 if (++i < N) ItinString += ", ";
260 }
261 }
262
263 //
264 // EmitStageAndOperandCycleData - Generate unique itinerary stages and
265 // operand cycle tables. Record itineraries for processors.
266 //
267 void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
245268 unsigned NItinClasses,
246269 std::map &ItinClassesMap,
247270 std::vector > &ProcList) {
253276 if (ProcItinList.size() < 2) return;
254277
255278 // Begin stages table
256 OS << "static const llvm::InstrStage Stages[] = {\n"
257 " { 0, 0, 0 }, // No itinerary\n";
279 std::string StageTable = "static const llvm::InstrStage Stages[] = {\n";
280 StageTable += " { 0, 0, 0 }, // No itinerary\n";
258281
259 unsigned StageCount = 1;
260 unsigned ItinEnum = 1;
261 std::map ItinMap;
282 // Begin operand cycle table
283 std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
284 OperandCycleTable += " 0, // No itinerary\n";
285
286 unsigned StageCount = 1, OperandCycleCount = 1;
287 unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
288 std::map ItinStageMap, ItinOperandCycleMap;
262289 for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
263290 // Next record
264291 Record *Proc = ProcItinList[i];
282309 Record *ItinData = ItinDataList[j];
283310
284311 // Get string and stage count
285 std::string ItinString;
312 std::string ItinStageString;
286313 unsigned NStages;
287 FormItineraryString(ItinData, ItinString, NStages);
288
289 // Check to see if it already exists
290 unsigned Find = ItinMap[ItinString];
291
292 // If new itinerary
293 if (Find == 0) {
294 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
295 OS << ItinString << ", // " << ItinEnum << "\n";
296 // Record Itin class number.
297 ItinMap[ItinString] = Find = StageCount;
298 StageCount += NStages;
299 ItinEnum++;
314 FormItineraryStageString(ItinData, ItinStageString, NStages);
315
316 // Get string and operand cycle count
317 std::string ItinOperandCycleString;
318 unsigned NOperandCycles;
319 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
320 NOperandCycles);
321
322 // Check to see if stage already exists and create if it doesn't
323 unsigned FindStage = 0;
324 if (NStages > 0) {
325 FindStage = ItinStageMap[ItinStageString];
326 if (FindStage == 0) {
327 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
328 StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
329 // Record Itin class number.
330 ItinStageMap[ItinStageString] = FindStage = StageCount;
331 StageCount += NStages;
332 ItinStageEnum++;
333 }
300334 }
301335
336 // Check to see if operand cycle already exists and create if it doesn't
337 unsigned FindOperandCycle = 0;
338 if (NOperandCycles > 0) {
339 FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
340 if (FindOperandCycle == 0) {
341 // Emit as cycle, // index
342 OperandCycleTable += ItinOperandCycleString + ", // " +
343 itostr(ItinOperandCycleEnum) + "\n";
344 // Record Itin class number.
345 ItinOperandCycleMap[ItinOperandCycleString] =
346 FindOperandCycle = OperandCycleCount;
347 OperandCycleCount += NOperandCycles;
348 ItinOperandCycleEnum++;
349 }
350 }
351
302352 // Set up itinerary as location and location + stage count
303 InstrItinerary Intinerary = { Find, Find + NStages };
353 InstrItinerary Intinerary = { FindStage, FindStage + NStages,
354 FindOperandCycle, FindOperandCycle + NOperandCycles};
304355
305356 // Locate where to inject into processor itinerary table
306357 const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
307 Find = ItinClassesMap[Name];
358 unsigned Find = ItinClassesMap[Name];
308359
309360 // Inject - empty slots will be 0, 0
310361 ItinList[Find] = Intinerary;
315366 }
316367
317368 // Closing stage
318 OS << " { 0, 0, 0 } // End itinerary\n";
319 // End stages table
320 OS << "};\n";
321
322 // Emit size of table
369 StageTable += " { 0, 0, 0 } // End itinerary\n";
370 StageTable += "};\n";
371
372 // Closing operand cycles
373 OperandCycleTable += " 0 // End itinerary\n";
374 OperandCycleTable += "};\n";
375
376 // Emit tables.
377 OS << StageTable;
378 OS << OperandCycleTable;
379
380 // Emit size of tables
323381 OS<<"\nenum {\n";
324 OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n";
382 OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
383 OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
325384 OS<<"};\n";
326385 }
327386
356415 for (unsigned j = 0, M = ItinList.size(); j < M;) {
357416 InstrItinerary &Intinerary = ItinList[j];
358417
359 // Emit in the form of { first, last } // index
360 if (Intinerary.First == 0) {
361 OS << " { 0, 0 }";
418 // Emit in the form of
419 // { firstStage, lastStage, firstCycle, lastCycle } // index
420 if (Intinerary.FirstStage == 0) {
421 OS << " { 0, 0, 0, 0 }";
362422 } else {
363 OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }";
423 OS << " { " << Intinerary.FirstStage << ", " <<
424 Intinerary.LastStage << ", " <<
425 Intinerary.FirstOperandCycle << ", " <<
426 Intinerary.LastOperandCycle << " }";
364427 }
365428
366429 // If more in list add comma
434497
435498 if (HasItineraries) {
436499 // Emit the stage data
437 EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList);
500 EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
438501 // Emit the processor itinerary data
439502 EmitProcessorData(OS, ProcList);
440503 // Emit the processor lookup data
481544 OS << "\n"
482545 << " InstrItinerary *Itinerary = (InstrItinerary *)"
483546 << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
484 << " InstrItins = InstrItineraryData(Stages, Itinerary);\n";
547 << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
485548 }
486549
487550 OS << " return Features.getCPU();\n"
3333 void CPUKeyValues(raw_ostream &OS);
3434 unsigned CollectAllItinClasses(raw_ostream &OS,
3535 std::map &ItinClassesMap);
36 void FormItineraryString(Record *ItinData, std::string &ItinString,
37 unsigned &NStages);
38 void EmitStageData(raw_ostream &OS, unsigned NItinClasses,
36 void FormItineraryStageString(Record *ItinData, std::string &ItinString,
37 unsigned &NStages);
38 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
39 unsigned &NOperandCycles);
40 void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
3941 std::map &ItinClassesMap,
4042 std::vector > &ProcList);
4143 void EmitProcessorData(raw_ostream &OS,