1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tablegen backend emits subtarget enumerations.
12 //===----------------------------------------------------------------------===//
14 #include "CodeGenTarget.h"
15 #include "CodeGenSchedule.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/MC/MCInstrItineraries.h"
19 #include "llvm/TableGen/Error.h"
20 #include "llvm/TableGen/Record.h"
21 #include "llvm/TableGen/TableGenBackend.h"
22 #include "llvm/Support/Debug.h"
30 class SubtargetEmitter {
31 // Each processor has a SchedClassDesc table with an entry for each SchedClass.
32 // The SchedClassDesc table indexes into a global write resource table, write
33 // latency table, and read advance table.
34 struct SchedClassTables {
35 std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
36 std::vector<MCWriteProcResEntry> WriteProcResources;
37 std::vector<MCWriteLatencyEntry> WriteLatencies;
38 std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
40 // Reserve an invalid entry at index 0
42 ProcSchedClasses.resize(1);
43 WriteProcResources.resize(1);
44 WriteLatencies.resize(1);
45 ReadAdvanceEntries.resize(1);
49 struct LessWriteProcResources {
50 bool operator()(const MCWriteProcResEntry &LHS,
51 const MCWriteProcResEntry &RHS) {
52 return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
56 RecordKeeper &Records;
57 CodeGenSchedModels &SchedModels;
60 void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
61 unsigned FeatureKeyValues(raw_ostream &OS);
62 unsigned CPUKeyValues(raw_ostream &OS);
63 void FormItineraryStageString(const std::string &Names,
64 Record *ItinData, std::string &ItinString,
66 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
67 unsigned &NOperandCycles);
68 void FormItineraryBypassString(const std::string &Names,
70 std::string &ItinString, unsigned NOperandCycles);
71 void EmitStageAndOperandCycleData(raw_ostream &OS,
72 std::vector<std::vector<InstrItinerary> >
74 void EmitItineraries(raw_ostream &OS,
75 std::vector<std::vector<InstrItinerary> >
77 void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
79 void EmitProcessorResources(const CodeGenProcModel &ProcModel,
81 Record *FindWriteResources(Record *WriteDef,
82 const CodeGenProcModel &ProcModel);
83 Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel);
84 void GenSchedClassTables(const CodeGenProcModel &ProcModel,
85 SchedClassTables &SchedTables);
86 void EmitProcessorModels(raw_ostream &OS);
87 void EmitProcessorLookup(raw_ostream &OS);
88 void EmitSchedModel(raw_ostream &OS);
89 void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
93 SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
94 Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
96 void run(raw_ostream &o);
99 } // End anonymous namespace
102 // Enumeration - Emit the specified class as an enumeration.
104 void SubtargetEmitter::Enumeration(raw_ostream &OS,
105 const char *ClassName,
107 // Get all records of class and sort
108 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
109 std::sort(DefList.begin(), DefList.end(), LessRecord());
111 unsigned N = DefList.size();
115 errs() << "Too many (> 64) subtarget features!\n";
119 OS << "namespace " << Target << " {\n";
121 // For bit flag enumerations with more than 32 items, emit constants.
122 // Emit an enum for everything else.
123 if (isBits && N > 32) {
125 for (unsigned i = 0; i < N; i++) {
127 Record *Def = DefList[i];
129 // Get and emit name and expression (1 << i)
130 OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
137 for (unsigned i = 0; i < N;) {
139 Record *Def = DefList[i];
142 OS << " " << Def->getName();
144 // If bit flags then emit expression (1 << i)
145 if (isBits) OS << " = " << " 1ULL << " << i;
147 // Depending on 'if more in the list' emit comma
148 if (++i < N) OS << ",";
161 // FeatureKeyValues - Emit data of all the subtarget features. Used by the
164 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
165 // Gather and sort all the features
166 std::vector<Record*> FeatureList =
167 Records.getAllDerivedDefinitions("SubtargetFeature");
169 if (FeatureList.empty())
172 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
174 // Begin feature table
175 OS << "// Sorted (by key) array of values for CPU features.\n"
176 << "extern const llvm::SubtargetFeatureKV " << Target
177 << "FeatureKV[] = {\n";
180 unsigned NumFeatures = 0;
181 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
183 Record *Feature = FeatureList[i];
185 const std::string &Name = Feature->getName();
186 const std::string &CommandLineName = Feature->getValueAsString("Name");
187 const std::string &Desc = Feature->getValueAsString("Desc");
189 if (CommandLineName.empty()) continue;
191 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
193 << "\"" << CommandLineName << "\", "
194 << "\"" << Desc << "\", "
195 << Target << "::" << Name << ", ";
197 const std::vector<Record*> &ImpliesList =
198 Feature->getValueAsListOfDefs("Implies");
200 if (ImpliesList.empty()) {
203 for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
204 OS << Target << "::" << ImpliesList[j]->getName();
205 if (++j < M) OS << " | ";
212 // Depending on 'if more in the list' emit comma
213 if ((i + 1) < N) OS << ",";
225 // CPUKeyValues - Emit data of all the subtarget processors. Used by command
228 unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
229 // Gather and sort processor information
230 std::vector<Record*> ProcessorList =
231 Records.getAllDerivedDefinitions("Processor");
232 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
234 // Begin processor table
235 OS << "// Sorted (by key) array of values for CPU subtype.\n"
236 << "extern const llvm::SubtargetFeatureKV " << Target
237 << "SubTypeKV[] = {\n";
239 // For each processor
240 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
242 Record *Processor = ProcessorList[i];
244 const std::string &Name = Processor->getValueAsString("Name");
245 const std::vector<Record*> &FeatureList =
246 Processor->getValueAsListOfDefs("Features");
248 // Emit as { "cpu", "description", f1 | f2 | ... fn },
250 << "\"" << Name << "\", "
251 << "\"Select the " << Name << " processor\", ";
253 if (FeatureList.empty()) {
256 for (unsigned j = 0, M = FeatureList.size(); j < M;) {
257 OS << Target << "::" << FeatureList[j]->getName();
258 if (++j < M) OS << " | ";
262 // The "0" is for the "implies" section of this data structure.
265 // Depending on 'if more in the list' emit comma
266 if (++i < N) OS << ",";
271 // End processor table
274 return ProcessorList.size();
278 // FormItineraryStageString - Compose a string containing the stage
279 // data initialization for the specified itinerary. N is the number
282 void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
284 std::string &ItinString,
287 const std::vector<Record*> &StageList =
288 ItinData->getValueAsListOfDefs("Stages");
291 unsigned N = NStages = StageList.size();
292 for (unsigned i = 0; i < N;) {
294 const Record *Stage = StageList[i];
296 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
297 int Cycles = Stage->getValueAsInt("Cycles");
298 ItinString += " { " + itostr(Cycles) + ", ";
301 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
304 for (unsigned j = 0, M = UnitList.size(); j < M;) {
305 // Add name and bitwise or
306 ItinString += Name + "FU::" + UnitList[j]->getName();
307 if (++j < M) ItinString += " | ";
310 int TimeInc = Stage->getValueAsInt("TimeInc");
311 ItinString += ", " + itostr(TimeInc);
313 int Kind = Stage->getValueAsInt("Kind");
314 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
318 if (++i < N) ItinString += ", ";
323 // FormItineraryOperandCycleString - Compose a string containing the
324 // operand cycle initialization for the specified itinerary. N is the
325 // number of operands that has cycles specified.
327 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
328 std::string &ItinString, unsigned &NOperandCycles) {
329 // Get operand cycle list
330 const std::vector<int64_t> &OperandCycleList =
331 ItinData->getValueAsListOfInts("OperandCycles");
333 // For each operand cycle
334 unsigned N = NOperandCycles = OperandCycleList.size();
335 for (unsigned i = 0; i < N;) {
336 // Next operand cycle
337 const int OCycle = OperandCycleList[i];
339 ItinString += " " + itostr(OCycle);
340 if (++i < N) ItinString += ", ";
344 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
346 std::string &ItinString,
347 unsigned NOperandCycles) {
348 const std::vector<Record*> &BypassList =
349 ItinData->getValueAsListOfDefs("Bypasses");
350 unsigned N = BypassList.size();
353 ItinString += Name + "Bypass::" + BypassList[i]->getName();
354 if (++i < NOperandCycles) ItinString += ", ";
356 for (; i < NOperandCycles;) {
358 if (++i < NOperandCycles) ItinString += ", ";
363 // EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
364 // cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
365 // by CodeGenSchedClass::Index.
367 void SubtargetEmitter::
368 EmitStageAndOperandCycleData(raw_ostream &OS,
369 std::vector<std::vector<InstrItinerary> >
372 // Multiple processor models may share an itinerary record. Emit it once.
373 SmallPtrSet<Record*, 8> ItinsDefSet;
375 // Emit functional units for all the itineraries.
376 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
377 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
379 if (!ItinsDefSet.insert(PI->ItinsDef))
382 std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
386 const std::string &Name = PI->ItinsDef->getName();
387 OS << "\n// Functional units for \"" << Name << "\"\n"
388 << "namespace " << Name << "FU {\n";
390 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
391 OS << " const unsigned " << FUs[j]->getName()
392 << " = 1 << " << j << ";\n";
396 std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
398 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
399 << "\"\n" << "namespace " << Name << "Bypass {\n";
401 OS << " const unsigned NoBypass = 0;\n";
402 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
403 OS << " const unsigned " << BPs[j]->getName()
404 << " = 1 << " << j << ";\n";
410 // Begin stages table
411 std::string StageTable = "\nextern const llvm::InstrStage " + Target +
413 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
415 // Begin operand cycle table
416 std::string OperandCycleTable = "extern const unsigned " + Target +
417 "OperandCycles[] = {\n";
418 OperandCycleTable += " 0, // No itinerary\n";
420 // Begin pipeline bypass table
421 std::string BypassTable = "extern const unsigned " + Target +
422 "ForwardingPaths[] = {\n";
423 BypassTable += " 0, // No itinerary\n";
425 // For each Itinerary across all processors, add a unique entry to the stages,
426 // operand cycles, and pipepine bypess tables. Then add the new Itinerary
427 // object with computed offsets to the ProcItinLists result.
428 unsigned StageCount = 1, OperandCycleCount = 1;
429 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
430 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
431 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
432 const CodeGenProcModel &ProcModel = *PI;
434 // Add process itinerary to the list.
435 ProcItinLists.resize(ProcItinLists.size()+1);
437 // If this processor defines no itineraries, then leave the itinerary list
439 std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
440 if (ProcModel.ItinDefList.empty())
443 // Reserve index==0 for NoItinerary.
444 ItinList.resize(SchedModels.numItineraryClasses()+1);
446 const std::string &Name = ProcModel.ItinsDef->getName();
448 // For each itinerary data
449 for (unsigned SchedClassIdx = 0,
450 SchedClassEnd = ProcModel.ItinDefList.size();
451 SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
453 // Next itinerary data
454 Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
456 // Get string and stage count
457 std::string ItinStageString;
458 unsigned NStages = 0;
460 FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
462 // Get string and operand cycle count
463 std::string ItinOperandCycleString;
464 unsigned NOperandCycles = 0;
465 std::string ItinBypassString;
467 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
470 FormItineraryBypassString(Name, ItinData, ItinBypassString,
474 // Check to see if stage already exists and create if it doesn't
475 unsigned FindStage = 0;
477 FindStage = ItinStageMap[ItinStageString];
478 if (FindStage == 0) {
479 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
480 StageTable += ItinStageString + ", // " + itostr(StageCount);
482 StageTable += "-" + itostr(StageCount + NStages - 1);
484 // Record Itin class number.
485 ItinStageMap[ItinStageString] = FindStage = StageCount;
486 StageCount += NStages;
490 // Check to see if operand cycle already exists and create if it doesn't
491 unsigned FindOperandCycle = 0;
492 if (NOperandCycles > 0) {
493 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
494 FindOperandCycle = ItinOperandMap[ItinOperandString];
495 if (FindOperandCycle == 0) {
496 // Emit as cycle, // index
497 OperandCycleTable += ItinOperandCycleString + ", // ";
498 std::string OperandIdxComment = itostr(OperandCycleCount);
499 if (NOperandCycles > 1)
500 OperandIdxComment += "-"
501 + itostr(OperandCycleCount + NOperandCycles - 1);
502 OperandCycleTable += OperandIdxComment + "\n";
503 // Record Itin class number.
504 ItinOperandMap[ItinOperandCycleString] =
505 FindOperandCycle = OperandCycleCount;
506 // Emit as bypass, // index
507 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
508 OperandCycleCount += NOperandCycles;
512 // Set up itinerary as location and location + stage count
513 int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
514 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
516 FindOperandCycle + NOperandCycles};
518 // Inject - empty slots will be 0, 0
519 ItinList[SchedClassIdx] = Intinerary;
524 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
525 StageTable += "};\n";
527 // Closing operand cycles
528 OperandCycleTable += " 0 // End operand cycles\n";
529 OperandCycleTable += "};\n";
531 BypassTable += " 0 // End bypass tables\n";
532 BypassTable += "};\n";
536 OS << OperandCycleTable;
541 // EmitProcessorData - Generate data for processor itineraries that were
542 // computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
543 // Itineraries for each processor. The Itinerary lists are indexed on
544 // CodeGenSchedClass::Index.
546 void SubtargetEmitter::
547 EmitItineraries(raw_ostream &OS,
548 std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
550 // Multiple processor models may share an itinerary record. Emit it once.
551 SmallPtrSet<Record*, 8> ItinsDefSet;
553 // For each processor's machine model
554 std::vector<std::vector<InstrItinerary> >::iterator
555 ProcItinListsIter = ProcItinLists.begin();
556 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
557 PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
559 Record *ItinsDef = PI->ItinsDef;
560 if (!ItinsDefSet.insert(ItinsDef))
563 // Get processor itinerary name
564 const std::string &Name = ItinsDef->getName();
566 // Get the itinerary list for the processor.
567 assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
568 std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
571 OS << "static const llvm::InstrItinerary ";
572 if (ItinList.empty()) {
573 OS << '*' << Name << " = 0;\n";
577 // Begin processor itinerary table
578 OS << Name << "[] = {\n";
580 // For each itinerary class in CodeGenSchedClass::Index order.
581 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
582 InstrItinerary &Intinerary = ItinList[j];
584 // Emit Itinerary in the form of
585 // { firstStage, lastStage, firstCycle, lastCycle } // index
587 Intinerary.NumMicroOps << ", " <<
588 Intinerary.FirstStage << ", " <<
589 Intinerary.LastStage << ", " <<
590 Intinerary.FirstOperandCycle << ", " <<
591 Intinerary.LastOperandCycle << " }" <<
592 ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
594 // End processor itinerary table
595 OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
600 // Emit either the value defined in the TableGen Record, or the default
601 // value defined in the C++ header. The Record is null if the processor does not
603 void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
604 const char *Name, char Separator) {
606 int V = R ? R->getValueAsInt(Name) : -1;
608 OS << V << Separator << " // " << Name;
610 OS << "MCSchedModel::Default" << Name << Separator;
614 void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
616 char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
618 OS << "\n// {Name, NumUnits, SuperIdx}\n";
619 OS << "static const llvm::MCProcResourceDesc "
620 << ProcModel.ModelName << "ProcResources" << "[] = {\n"
621 << " {DBGFIELD(\"InvalidUnit\") 0, 0}" << Sep << "\n";
623 for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
624 Record *PRDef = ProcModel.ProcResourceDefs[i];
627 unsigned SuperIdx = 0;
628 Record *SuperDef = 0;
629 if (PRDef->getValueInit("Super")->isComplete()) {
631 SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
632 SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
634 // Emit the ProcResourceDesc
637 OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
638 if (PRDef->getName().size() < 15)
639 OS.indent(15 - PRDef->getName().size());
640 OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
641 << "}" << Sep << " // #" << i+1;
643 OS << ", Super=" << SuperDef->getName();
649 // Find the WriteRes Record that defines processor resources for this
651 Record *SubtargetEmitter::FindWriteResources(
652 Record *WriteDef, const CodeGenProcModel &ProcModel) {
654 // Check if the SchedWrite is already subtarget-specific and directly
655 // specifies a set of processor resources.
656 if (WriteDef->isSubClassOf("SchedWriteRes"))
659 // Check this processor's list of write resources.
660 for (RecIter WRI = ProcModel.WriteResDefs.begin(),
661 WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
662 if (!(*WRI)->isSubClassOf("WriteRes"))
664 if (WriteDef == (*WRI)->getValueAsDef("WriteType"))
667 throw TGError(ProcModel.ModelDef->getLoc(),
668 std::string("Processor does not define resources for ")
669 + WriteDef->getName());
672 /// Find the ReadAdvance record for the given SchedRead on this processor or
674 Record *SubtargetEmitter::FindReadAdvance(Record *ReadDef,
675 const CodeGenProcModel &ProcModel) {
676 // Check for SchedReads that directly specify a ReadAdvance.
677 if (ReadDef->isSubClassOf("SchedReadAdvance"))
680 // Check this processor's ReadAdvanceList.
681 for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
682 RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
683 if (!(*RAI)->isSubClassOf("ReadAdvance"))
685 if (ReadDef == (*RAI)->getValueAsDef("ReadType"))
688 if (ReadDef->getName() != "ReadDefault") {
689 throw TGError(ProcModel.ModelDef->getLoc(),
690 std::string("Processor does not define resources for ")
691 + ReadDef->getName());
696 // Generate the SchedClass table for this processor and update global
697 // tables. Must be called for each processor in order.
698 void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
699 SchedClassTables &SchedTables) {
700 SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
701 if (!ProcModel.hasInstrSchedModel())
704 std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
705 for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
706 SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
707 SCTab.resize(SCTab.size() + 1);
708 MCSchedClassDesc &SCDesc = SCTab.back();
709 SCDesc.Name = SCI->Name.c_str();
710 SCDesc.NumMicroOps = 0;
711 SCDesc.BeginGroup = false;
712 SCDesc.EndGroup = false;
713 SCDesc.WriteProcResIdx = 0;
714 SCDesc.WriteLatencyIdx = 0;
715 SCDesc.ReadAdvanceIdx = 0;
717 // A Variant SchedClass has no resources of its own.
718 if (!SCI->Transitions.empty()) {
719 SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
723 // Determine if the SchedClass is actually reachable on this processor. If
724 // not don't try to locate the processor resources, it will fail.
725 // If ProcIndices contains 0, this class applies to all processors.
726 assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
727 if (SCI->ProcIndices[0] != 0) {
728 IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
729 SCI->ProcIndices.end(), ProcModel.Index);
730 if (PIPos == SCI->ProcIndices.end())
733 IdxVec Writes = SCI->Writes;
734 IdxVec Reads = SCI->Reads;
735 if (SCI->ItinClassDef) {
736 assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs");
737 // Check this processor's itinerary class resources.
738 for (RecIter II = ProcModel.ItinRWDefs.begin(),
739 IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
740 RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
741 if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
743 SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
748 if (Writes.empty()) {
749 DEBUG(dbgs() << ProcModel.ItinsDef->getName()
750 << " does not have resources for itinerary class "
751 << SCI->ItinClassDef->getName() << '\n');
754 else if (!SCI->InstRWs.empty()) {
755 assert(SCI->Writes.empty() && SCI->Reads.empty() &&
756 "InstRW class should not have its own ReadWrites");
758 for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
760 Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
761 if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
767 SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
771 // Sum resources across all operand writes.
772 std::vector<MCWriteProcResEntry> WriteProcResources;
773 std::vector<MCWriteLatencyEntry> WriteLatencies;
774 std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
775 for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
777 SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false);
779 // For each operand, create a latency entry.
780 MCWriteLatencyEntry WLEntry;
782 WLEntry.WriteResourceID = WriteSeq.back();
784 for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
787 Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef;
788 Record *WriteRes = FindWriteResources(WriteDef, ProcModel);
790 // Mark the parent class as invalid for unsupported write types.
791 if (WriteRes->getValueAsBit("Unsupported")) {
792 SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
795 WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
796 SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
797 SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
798 SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
800 // Create an entry for each ProcResource listed in WriteRes.
801 RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
802 std::vector<int64_t> Cycles =
803 WriteRes->getValueAsListOfInts("ResourceCycles");
804 for (unsigned PRIdx = 0, PREnd = PRVec.size();
805 PRIdx != PREnd; ++PRIdx) {
806 MCWriteProcResEntry WPREntry;
807 WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
808 assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
809 if (Cycles.size() > PRIdx)
810 WPREntry.Cycles = Cycles[PRIdx];
813 WriteProcResources.push_back(WPREntry);
816 WriteLatencies.push_back(WLEntry);
818 // Create an entry for each operand Read in this SchedClass.
819 // Entries must be sorted first by UseIdx then by WriteResourceID.
820 for (unsigned UseIdx = 0, EndIdx = Reads.size();
821 UseIdx != EndIdx; ++UseIdx) {
822 Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef;
823 Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel);
827 // Mark the parent class as invalid for unsupported write types.
828 if (ReadAdvance->getValueAsBit("Unsupported")) {
829 SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
832 RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
834 if (ValidWrites.empty())
835 WriteIDs.push_back(0);
837 for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
839 WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
842 std::sort(WriteIDs.begin(), WriteIDs.end());
843 for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
844 MCReadAdvanceEntry RAEntry;
845 RAEntry.UseIdx = UseIdx;
846 RAEntry.WriteResourceID = *WI;
847 RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
848 ReadAdvanceEntries.push_back(RAEntry);
851 if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
852 WriteProcResources.clear();
853 WriteLatencies.clear();
854 ReadAdvanceEntries.clear();
856 // Add the information for this SchedClass to the global tables using basic
859 // WritePrecRes entries are sorted by ProcResIdx.
860 std::sort(WriteProcResources.begin(), WriteProcResources.end(),
861 LessWriteProcResources());
863 SCDesc.NumWriteProcResEntries = WriteProcResources.size();
864 std::vector<MCWriteProcResEntry>::iterator WPRPos =
865 std::search(SchedTables.WriteProcResources.begin(),
866 SchedTables.WriteProcResources.end(),
867 WriteProcResources.begin(), WriteProcResources.end());
868 if (WPRPos != SchedTables.WriteProcResources.end())
869 SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
871 SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
872 SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
873 WriteProcResources.end());
875 // Latency entries must remain in operand order.
876 SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
877 std::vector<MCWriteLatencyEntry>::iterator WLPos =
878 std::search(SchedTables.WriteLatencies.begin(),
879 SchedTables.WriteLatencies.end(),
880 WriteLatencies.begin(), WriteLatencies.end());
881 if (WLPos != SchedTables.WriteLatencies.end())
882 SCDesc.WriteLatencyIdx = WLPos - SchedTables.WriteLatencies.begin();
884 SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
885 SchedTables.WriteLatencies.insert(WLPos, WriteLatencies.begin(),
886 WriteLatencies.end());
888 // ReadAdvanceEntries must remain in operand order.
889 SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
890 std::vector<MCReadAdvanceEntry>::iterator RAPos =
891 std::search(SchedTables.ReadAdvanceEntries.begin(),
892 SchedTables.ReadAdvanceEntries.end(),
893 ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
894 if (RAPos != SchedTables.ReadAdvanceEntries.end())
895 SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
897 SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
898 SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
899 ReadAdvanceEntries.end());
904 void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
905 // For each processor model.
906 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
907 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
908 // Emit processor resource table.
909 if (PI->hasInstrSchedModel())
910 EmitProcessorResources(*PI, OS);
911 else if(!PI->ProcResourceDefs.empty())
912 throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
913 "ProcResources without defining WriteRes SchedWriteRes");
915 // Begin processor itinerary properties
917 OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
918 EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
919 EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
920 EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
921 EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
922 EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
923 if (SchedModels.hasItineraryClasses())
924 OS << " " << PI->ItinsDef->getName() << ");\n";
926 OS << " 0); // No Itinerary\n";
931 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
933 void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
934 // Gather and sort processor information
935 std::vector<Record*> ProcessorList =
936 Records.getAllDerivedDefinitions("Processor");
937 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
939 // Begin processor table
941 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
942 << "extern const llvm::SubtargetInfoKV "
943 << Target << "ProcSchedKV[] = {\n";
945 // For each processor
946 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
948 Record *Processor = ProcessorList[i];
950 const std::string &Name = Processor->getValueAsString("Name");
951 const std::string &ProcModelName =
952 SchedModels.getModelForProc(Processor).ModelName;
954 // Emit as { "cpu", procinit },
955 OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
957 // Depending on ''if more in the list'' emit comma
958 if (++i < N) OS << ",";
963 // End processor table
968 // EmitSchedModel - Emits all scheduling model tables, folding common patterns.
970 void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
971 OS << "#ifdef DBGFIELD\n"
972 << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
974 << "#ifndef NDEBUG\n"
975 << "#define DBGFIELD(x) x,\n"
977 << "#define DBGFIELD(x)\n"
980 if (SchedModels.hasItineraryClasses()) {
981 std::vector<std::vector<InstrItinerary> > ProcItinLists;
982 // Emit the stage data
983 EmitStageAndOperandCycleData(OS, ProcItinLists);
984 EmitItineraries(OS, ProcItinLists);
987 // Emit the processor machine model
988 EmitProcessorModels(OS);
989 // Emit the processor lookup data
990 EmitProcessorLookup(OS);
992 SchedClassTables SchedTables;
993 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
994 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
995 GenSchedClassTables(*PI, SchedTables);
998 OS << "#undef DBGFIELD";
1002 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
1003 // the subtarget features string.
1005 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
1006 unsigned NumFeatures,
1007 unsigned NumProcs) {
1008 std::vector<Record*> Features =
1009 Records.getAllDerivedDefinitions("SubtargetFeature");
1010 std::sort(Features.begin(), Features.end(), LessRecord());
1012 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1013 << "// subtarget options.\n"
1016 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1017 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
1018 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
1020 if (Features.empty()) {
1025 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
1027 for (unsigned i = 0; i < Features.size(); i++) {
1029 Record *R = Features[i];
1030 const std::string &Instance = R->getName();
1031 const std::string &Value = R->getValueAsString("Value");
1032 const std::string &Attribute = R->getValueAsString("Attribute");
1034 if (Value=="true" || Value=="false")
1035 OS << " if ((Bits & " << Target << "::"
1036 << Instance << ") != 0) "
1037 << Attribute << " = " << Value << ";\n";
1039 OS << " if ((Bits & " << Target << "::"
1040 << Instance << ") != 0 && "
1041 << Attribute << " < " << Value << ") "
1042 << Attribute << " = " << Value << ";\n";
1049 // SubtargetEmitter::run - Main subtarget enumeration emitter.
1051 void SubtargetEmitter::run(raw_ostream &OS) {
1052 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1054 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1055 OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1057 OS << "namespace llvm {\n";
1058 Enumeration(OS, "SubtargetFeature", true);
1059 OS << "} // End llvm namespace \n";
1060 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1062 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
1063 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1065 OS << "namespace llvm {\n";
1067 OS << "namespace {\n";
1069 unsigned NumFeatures = FeatureKeyValues(OS);
1071 unsigned NumProcs = CPUKeyValues(OS);
1079 // MCInstrInfo initialization routine.
1080 OS << "static inline void Init" << Target
1081 << "MCSubtargetInfo(MCSubtargetInfo *II, "
1082 << "StringRef TT, StringRef CPU, StringRef FS) {\n";
1083 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
1085 OS << Target << "FeatureKV, ";
1089 OS << Target << "SubTypeKV, ";
1092 if (SchedModels.hasItineraryClasses()) {
1093 OS << Target << "ProcSchedKV, "
1094 << Target << "Stages, "
1095 << Target << "OperandCycles, "
1096 << Target << "ForwardingPaths, ";
1098 OS << "0, 0, 0, 0, ";
1099 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1101 OS << "} // End llvm namespace \n";
1103 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
1105 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
1106 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
1108 OS << "#include \"llvm/Support/Debug.h\"\n";
1109 OS << "#include \"llvm/Support/raw_ostream.h\"\n";
1110 ParseFeaturesFunction(OS, NumFeatures, NumProcs);
1112 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
1114 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
1115 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
1116 OS << "#undef GET_SUBTARGETINFO_HEADER\n";
1118 std::string ClassName = Target + "GenSubtargetInfo";
1119 OS << "namespace llvm {\n";
1120 OS << "class DFAPacketizer;\n";
1121 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
1122 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
1123 << "StringRef FS);\n"
1125 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1128 OS << "} // End llvm namespace \n";
1130 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
1132 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
1133 OS << "#undef GET_SUBTARGETINFO_CTOR\n";
1135 OS << "namespace llvm {\n";
1136 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
1137 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1138 if (SchedModels.hasItineraryClasses()) {
1139 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1140 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
1141 OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1142 OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1145 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
1146 << "StringRef FS)\n"
1147 << " : TargetSubtargetInfo() {\n"
1148 << " InitMCSubtargetInfo(TT, CPU, FS, ";
1150 OS << Target << "FeatureKV, ";
1154 OS << Target << "SubTypeKV, ";
1157 if (SchedModels.hasItineraryClasses()) {
1158 OS << Target << "ProcSchedKV, "
1159 << Target << "Stages, "
1160 << Target << "OperandCycles, "
1161 << Target << "ForwardingPaths, ";
1163 OS << "0, 0, 0, 0, ";
1164 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1165 OS << "} // End llvm namespace \n";
1167 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1172 void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
1173 CodeGenTarget CGTarget(RK);
1174 SubtargetEmitter(RK, CGTarget).run(OS);
1177 } // End llvm namespace