xref: /llvm-project/llvm/utils/TableGen/SubtargetEmitter.cpp (revision 517334bdb83deaae3be6fbc4fa5f1d721b01c0f0)
1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend emits subtarget enumerations.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Common/CodeGenHwModes.h"
14 #include "Common/CodeGenSchedule.h"
15 #include "Common/CodeGenTarget.h"
16 #include "Common/PredicateExpander.h"
17 #include "Common/Utils.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallPtrSet.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/ADT/StringMap.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/MC/MCInstrItineraries.h"
26 #include "llvm/MC/MCSchedule.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Format.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/TableGen/Error.h"
31 #include "llvm/TableGen/Record.h"
32 #include "llvm/TableGen/TableGenBackend.h"
33 #include "llvm/TargetParser/SubtargetFeature.h"
34 #include <algorithm>
35 #include <cassert>
36 #include <cstdint>
37 #include <iterator>
38 #include <string>
39 #include <vector>
40 
41 using namespace llvm;
42 
43 #define DEBUG_TYPE "subtarget-emitter"
44 
45 namespace {
46 
47 using FeatureMapTy = DenseMap<const Record *, unsigned>;
48 
49 /// Sorting predicate to sort record pointers by their
50 /// FieldName field.
51 struct LessRecordFieldFieldName {
52   bool operator()(const Record *Rec1, const Record *Rec2) const {
53     return Rec1->getValueAsString("FieldName") <
54            Rec2->getValueAsString("FieldName");
55   }
56 };
57 
58 class SubtargetEmitter {
59   // Each processor has a SchedClassDesc table with an entry for each
60   // SchedClass. The SchedClassDesc table indexes into a global write resource
61   // table, write latency table, and read advance table.
62   struct SchedClassTables {
63     std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses;
64     std::vector<MCWriteProcResEntry> WriteProcResources;
65     std::vector<MCWriteLatencyEntry> WriteLatencies;
66     std::vector<std::string> WriterNames;
67     std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
68 
69     // Reserve an invalid entry at index 0
70     SchedClassTables() {
71       ProcSchedClasses.resize(1);
72       WriteProcResources.resize(1);
73       WriteLatencies.resize(1);
74       WriterNames.push_back("InvalidWrite");
75       ReadAdvanceEntries.resize(1);
76     }
77   };
78 
79   struct LessWriteProcResources {
80     bool operator()(const MCWriteProcResEntry &LHS,
81                     const MCWriteProcResEntry &RHS) {
82       return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
83     }
84   };
85 
86   CodeGenTarget TGT;
87   const RecordKeeper &Records;
88   CodeGenSchedModels &SchedModels;
89   std::string Target;
90 
91   FeatureMapTy enumeration(raw_ostream &OS);
92   void emitSubtargetInfoMacroCalls(raw_ostream &OS);
93   unsigned featureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
94   unsigned cpuKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
95   unsigned cpuNames(raw_ostream &OS);
96   void formItineraryStageString(const std::string &Names,
97                                 const Record *ItinData, std::string &ItinString,
98                                 unsigned &NStages);
99   void formItineraryOperandCycleString(const Record *ItinData,
100                                        std::string &ItinString,
101                                        unsigned &NOperandCycles);
102   void formItineraryBypassString(const std::string &Names,
103                                  const Record *ItinData,
104                                  std::string &ItinString,
105                                  unsigned NOperandCycles);
106   void emitStageAndOperandCycleData(
107       raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists);
108   void emitItineraries(raw_ostream &OS,
109                        std::vector<std::vector<InstrItinerary>> &ProcItinLists);
110   unsigned emitRegisterFileTables(const CodeGenProcModel &ProcModel,
111                                   raw_ostream &OS);
112   void emitLoadStoreQueueInfo(const CodeGenProcModel &ProcModel,
113                               raw_ostream &OS);
114   void emitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
115                               raw_ostream &OS);
116   void emitProcessorProp(raw_ostream &OS, const Record *R, StringRef Name,
117                          char Separator);
118   void emitProcessorResourceSubUnits(const CodeGenProcModel &ProcModel,
119                                      raw_ostream &OS);
120   void emitProcessorResources(const CodeGenProcModel &ProcModel,
121                               raw_ostream &OS);
122   const Record *findWriteResources(const CodeGenSchedRW &SchedWrite,
123                                    const CodeGenProcModel &ProcModel);
124   const Record *findReadAdvance(const CodeGenSchedRW &SchedRead,
125                                 const CodeGenProcModel &ProcModel);
126   void expandProcResources(ConstRecVec &PRVec,
127                            std::vector<int64_t> &ReleaseAtCycles,
128                            std::vector<int64_t> &AcquireAtCycles,
129                            const CodeGenProcModel &ProcModel);
130   void genSchedClassTables(const CodeGenProcModel &ProcModel,
131                            SchedClassTables &SchedTables);
132   void emitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
133   void emitProcessorModels(raw_ostream &OS);
134   void emitSchedModelHelpers(const std::string &ClassName, raw_ostream &OS);
135   void emitSchedModelHelpersImpl(raw_ostream &OS,
136                                  bool OnlyExpandMCInstPredicates = false);
137   void emitGenMCSubtargetInfo(raw_ostream &OS);
138   void emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS);
139 
140   void emitSchedModel(raw_ostream &OS);
141   void emitGetMacroFusions(const std::string &ClassName, raw_ostream &OS);
142   void emitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
143   void parseFeaturesFunction(raw_ostream &OS);
144 
145 public:
146   SubtargetEmitter(const RecordKeeper &R)
147       : TGT(R), Records(R), SchedModels(TGT.getSchedModels()),
148         Target(TGT.getName()) {}
149 
150   void run(raw_ostream &O);
151 };
152 
153 } // end anonymous namespace
154 
155 //
156 // Enumeration - Emit the specified class as an enumeration.
157 //
158 FeatureMapTy SubtargetEmitter::enumeration(raw_ostream &OS) {
159   ArrayRef<const Record *> DefList =
160       Records.getAllDerivedDefinitions("SubtargetFeature");
161 
162   unsigned N = DefList.size();
163   if (N == 0)
164     return FeatureMapTy();
165   if (N + 1 > MAX_SUBTARGET_FEATURES)
166     PrintFatalError(
167         "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
168 
169   OS << "namespace " << Target << " {\n";
170 
171   // Open enumeration.
172   OS << "enum {\n";
173 
174   FeatureMapTy FeatureMap;
175   // For each record
176   for (unsigned I = 0; I < N; ++I) {
177     // Next record
178     const Record *Def = DefList[I];
179 
180     // Get and emit name
181     OS << "  " << Def->getName() << " = " << I << ",\n";
182 
183     // Save the index for this feature.
184     FeatureMap[Def] = I;
185   }
186 
187   OS << "  "
188      << "NumSubtargetFeatures = " << N << "\n";
189 
190   // Close enumeration and namespace
191   OS << "};\n";
192   OS << "} // end namespace " << Target << "\n";
193   return FeatureMap;
194 }
195 
196 static void printFeatureMask(raw_ostream &OS,
197                              ArrayRef<const Record *> FeatureList,
198                              const FeatureMapTy &FeatureMap) {
199   std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
200   for (const Record *Feature : FeatureList) {
201     unsigned Bit = FeatureMap.lookup(Feature);
202     Mask[Bit / 64] |= 1ULL << (Bit % 64);
203   }
204 
205   OS << "{ { { ";
206   for (unsigned I = 0; I != Mask.size(); ++I) {
207     OS << "0x";
208     OS.write_hex(Mask[I]);
209     OS << "ULL, ";
210   }
211   OS << "} } }";
212 }
213 
214 /// Emit some information about the SubtargetFeature as calls to a macro so
215 /// that they can be used from C++.
216 void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) {
217   OS << "\n#ifdef GET_SUBTARGETINFO_MACRO\n";
218 
219   std::vector<const Record *> FeatureList =
220       Records.getAllDerivedDefinitions("SubtargetFeature");
221   llvm::sort(FeatureList, LessRecordFieldFieldName());
222 
223   for (const Record *Feature : FeatureList) {
224     const StringRef FieldName = Feature->getValueAsString("FieldName");
225     const StringRef Value = Feature->getValueAsString("Value");
226 
227     // Only handle boolean features for now, excluding BitVectors and enums.
228     const bool IsBool = (Value == "false" || Value == "true") &&
229                         !StringRef(FieldName).contains('[');
230     if (!IsBool)
231       continue;
232 
233     // Some features default to true, with values set to false if enabled.
234     const char *Default = Value == "false" ? "true" : "false";
235 
236     // Define the getter with lowercased first char: xxxYyy() { return XxxYyy; }
237     const std::string Getter =
238         FieldName.substr(0, 1).lower() + FieldName.substr(1).str();
239 
240     OS << "GET_SUBTARGETINFO_MACRO(" << FieldName << ", " << Default << ", "
241        << Getter << ")\n";
242   }
243   OS << "#undef GET_SUBTARGETINFO_MACRO\n";
244   OS << "#endif // GET_SUBTARGETINFO_MACRO\n\n";
245 
246   OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
247   OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
248 
249   if (Target == "AArch64")
250     OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n";
251 }
252 
253 //
254 // FeatureKeyValues - Emit data of all the subtarget features.  Used by the
255 // command line.
256 //
257 unsigned SubtargetEmitter::featureKeyValues(raw_ostream &OS,
258                                             const FeatureMapTy &FeatureMap) {
259   std::vector<const Record *> FeatureList =
260       Records.getAllDerivedDefinitions("SubtargetFeature");
261 
262   // Remove features with empty name.
263   llvm::erase_if(FeatureList, [](const Record *Rec) {
264     return Rec->getValueAsString("Name").empty();
265   });
266   if (FeatureList.empty())
267     return 0;
268 
269   // Sort and check duplicate Feature name.
270   sortAndReportDuplicates(FeatureList, "Feature");
271 
272   // Begin feature table.
273   OS << "// Sorted (by key) array of values for CPU features.\n"
274      << "extern const llvm::SubtargetFeatureKV " << Target
275      << "FeatureKV[] = {\n";
276 
277   for (const Record *Feature : FeatureList) {
278     // Next feature
279     StringRef Name = Feature->getName();
280     StringRef CommandLineName = Feature->getValueAsString("Name");
281     StringRef Desc = Feature->getValueAsString("Desc");
282 
283     // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in
284     // } }
285     OS << "  { "
286        << "\"" << CommandLineName << "\", "
287        << "\"" << Desc << "\", " << Target << "::" << Name << ", ";
288 
289     ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
290 
291     printFeatureMask(OS, ImpliesList, FeatureMap);
292 
293     OS << " },\n";
294   }
295 
296   // End feature table.
297   OS << "};\n";
298 
299   return FeatureList.size();
300 }
301 
302 unsigned SubtargetEmitter::cpuNames(raw_ostream &OS) {
303   // Begin processor name table.
304   OS << "// Sorted array of names of CPU subtypes, including aliases.\n"
305      << "extern const llvm::StringRef " << Target << "Names[] = {\n";
306 
307   std::vector<const Record *> ProcessorList =
308       Records.getAllDerivedDefinitions("Processor");
309 
310   std::vector<const Record *> ProcessorAliasList =
311       Records.getAllDerivedDefinitionsIfDefined("ProcessorAlias");
312 
313   SmallVector<StringRef> Names;
314   Names.reserve(ProcessorList.size() + ProcessorAliasList.size());
315 
316   for (const Record *Processor : ProcessorList) {
317     StringRef Name = Processor->getValueAsString("Name");
318     Names.push_back(Name);
319   }
320 
321   for (const Record *Rec : ProcessorAliasList) {
322     auto Name = Rec->getValueAsString("Name");
323     Names.push_back(Name);
324   }
325 
326   llvm::sort(Names);
327   llvm::interleave(
328       Names, OS, [&](StringRef Name) { OS << '"' << Name << '"'; }, ",\n");
329 
330   // End processor name table.
331   OS << "};\n";
332 
333   return Names.size();
334 }
335 
336 //
337 // CPUKeyValues - Emit data of all the subtarget processors.  Used by command
338 // line.
339 //
340 unsigned SubtargetEmitter::cpuKeyValues(raw_ostream &OS,
341                                         const FeatureMapTy &FeatureMap) {
342   // Gather and sort processor information
343   std::vector<const Record *> ProcessorList =
344       Records.getAllDerivedDefinitions("Processor");
345   llvm::sort(ProcessorList, LessRecordFieldName());
346 
347   // Note that unlike `FeatureKeyValues`, here we do not need to check for
348   // duplicate processors, since that is already done when the SubtargetEmitter
349   // constructor calls `getSchedModels` to build a `CodeGenSchedModels` object,
350   // which does the duplicate processor check.
351 
352   // Begin processor table.
353   OS << "// Sorted (by key) array of values for CPU subtype.\n"
354      << "extern const llvm::SubtargetSubTypeKV " << Target
355      << "SubTypeKV[] = {\n";
356 
357   for (const Record *Processor : ProcessorList) {
358     StringRef Name = Processor->getValueAsString("Name");
359     ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features");
360     ConstRecVec TuneFeatureList =
361         Processor->getValueAsListOfDefs("TuneFeatures");
362 
363     // Emit as "{ "cpu", "description", 0, { f1 , f2 , ... fn } },".
364     OS << " { "
365        << "\"" << Name << "\", ";
366 
367     printFeatureMask(OS, FeatureList, FeatureMap);
368     OS << ", ";
369     printFeatureMask(OS, TuneFeatureList, FeatureMap);
370 
371     // Emit the scheduler model pointer.
372     const std::string &ProcModelName =
373         SchedModels.getModelForProc(Processor).ModelName;
374     OS << ", &" << ProcModelName << " },\n";
375   }
376 
377   // End processor table.
378   OS << "};\n";
379 
380   return ProcessorList.size();
381 }
382 
383 //
384 // FormItineraryStageString - Compose a string containing the stage
385 // data initialization for the specified itinerary.  N is the number
386 // of stages.
387 //
388 void SubtargetEmitter::formItineraryStageString(const std::string &Name,
389                                                 const Record *ItinData,
390                                                 std::string &ItinString,
391                                                 unsigned &NStages) {
392   // Get states list
393   ConstRecVec StageList = ItinData->getValueAsListOfDefs("Stages");
394 
395   // For each stage
396   unsigned N = NStages = StageList.size();
397   for (unsigned I = 0; I < N;) {
398     // Next stage
399     const Record *Stage = StageList[I];
400 
401     // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
402     int Cycles = Stage->getValueAsInt("Cycles");
403     ItinString += "  { " + itostr(Cycles) + ", ";
404 
405     // Get unit list
406     ConstRecVec UnitList = Stage->getValueAsListOfDefs("Units");
407 
408     // For each unit
409     for (unsigned J = 0, M = UnitList.size(); J < M;) {
410       // Add name and bitwise or
411       ItinString += Name + "FU::" + UnitList[J]->getName().str();
412       if (++J < M)
413         ItinString += " | ";
414     }
415 
416     int TimeInc = Stage->getValueAsInt("TimeInc");
417     ItinString += ", " + itostr(TimeInc);
418 
419     int Kind = Stage->getValueAsInt("Kind");
420     ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
421 
422     // Close off stage
423     ItinString += " }";
424     if (++I < N)
425       ItinString += ", ";
426   }
427 }
428 
429 //
430 // FormItineraryOperandCycleString - Compose a string containing the
431 // operand cycle initialization for the specified itinerary.  N is the
432 // number of operands that has cycles specified.
433 //
434 void SubtargetEmitter::formItineraryOperandCycleString(
435     const Record *ItinData, std::string &ItinString, unsigned &NOperandCycles) {
436   // Get operand cycle list
437   std::vector<int64_t> OperandCycleList =
438       ItinData->getValueAsListOfInts("OperandCycles");
439 
440   // For each operand cycle
441   NOperandCycles = OperandCycleList.size();
442   ListSeparator LS;
443   for (int OCycle : OperandCycleList) {
444     // Next operand cycle
445     ItinString += LS;
446     ItinString += "  " + itostr(OCycle);
447   }
448 }
449 
450 void SubtargetEmitter::formItineraryBypassString(const std::string &Name,
451                                                  const Record *ItinData,
452                                                  std::string &ItinString,
453                                                  unsigned NOperandCycles) {
454   ConstRecVec BypassList = ItinData->getValueAsListOfDefs("Bypasses");
455   unsigned N = BypassList.size();
456   unsigned I = 0;
457   ListSeparator LS;
458   for (; I < N; ++I) {
459     ItinString += LS;
460     ItinString += Name + "Bypass::" + BypassList[I]->getName().str();
461   }
462   for (; I < NOperandCycles; ++I) {
463     ItinString += LS;
464     ItinString += " 0";
465   }
466 }
467 
468 //
469 // EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
470 // cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
471 // by CodeGenSchedClass::Index.
472 //
473 void SubtargetEmitter::emitStageAndOperandCycleData(
474     raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
475   // Multiple processor models may share an itinerary record. Emit it once.
476   SmallPtrSet<const Record *, 8> ItinsDefSet;
477 
478   // Emit functional units for all the itineraries.
479   for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
480 
481     if (!ItinsDefSet.insert(ProcModel.ItinsDef).second)
482       continue;
483 
484     ConstRecVec FUs = ProcModel.ItinsDef->getValueAsListOfDefs("FU");
485     if (FUs.empty())
486       continue;
487 
488     StringRef Name = ProcModel.ItinsDef->getName();
489     OS << "\n// Functional units for \"" << Name << "\"\n"
490        << "namespace " << Name << "FU {\n";
491 
492     for (unsigned J = 0, FUN = FUs.size(); J < FUN; ++J)
493       OS << "  const InstrStage::FuncUnits " << FUs[J]->getName()
494          << " = 1ULL << " << J << ";\n";
495 
496     OS << "} // end namespace " << Name << "FU\n";
497 
498     ConstRecVec BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
499     if (!BPs.empty()) {
500       OS << "\n// Pipeline forwarding paths for itineraries \"" << Name
501          << "\"\n"
502          << "namespace " << Name << "Bypass {\n";
503 
504       OS << "  const unsigned NoBypass = 0;\n";
505       for (unsigned J = 0, BPN = BPs.size(); J < BPN; ++J)
506         OS << "  const unsigned " << BPs[J]->getName() << " = 1 << " << J
507            << ";\n";
508 
509       OS << "} // end namespace " << Name << "Bypass\n";
510     }
511   }
512 
513   // Begin stages table
514   std::string StageTable =
515       "\nextern const llvm::InstrStage " + Target + "Stages[] = {\n";
516   StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
517 
518   // Begin operand cycle table
519   std::string OperandCycleTable =
520       "extern const unsigned " + Target + "OperandCycles[] = {\n";
521   OperandCycleTable += "  0, // No itinerary\n";
522 
523   // Begin pipeline bypass table
524   std::string BypassTable =
525       "extern const unsigned " + Target + "ForwardingPaths[] = {\n";
526   BypassTable += " 0, // No itinerary\n";
527 
528   // For each Itinerary across all processors, add a unique entry to the stages,
529   // operand cycles, and pipeline bypass tables. Then add the new Itinerary
530   // object with computed offsets to the ProcItinLists result.
531   unsigned StageCount = 1, OperandCycleCount = 1;
532   StringMap<unsigned> ItinStageMap, ItinOperandMap;
533   for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
534     // Add process itinerary to the list.
535     std::vector<InstrItinerary> &ItinList = ProcItinLists.emplace_back();
536 
537     // If this processor defines no itineraries, then leave the itinerary list
538     // empty.
539     if (!ProcModel.hasItineraries())
540       continue;
541 
542     StringRef Name = ProcModel.ItinsDef->getName();
543 
544     ItinList.resize(SchedModels.numInstrSchedClasses());
545     assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins");
546 
547     for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size();
548          SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
549 
550       // Next itinerary data
551       const Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
552 
553       // Get string and stage count
554       std::string ItinStageString;
555       unsigned NStages = 0;
556       if (ItinData)
557         formItineraryStageString(std::string(Name), ItinData, ItinStageString,
558                                  NStages);
559 
560       // Get string and operand cycle count
561       std::string ItinOperandCycleString;
562       unsigned NOperandCycles = 0;
563       std::string ItinBypassString;
564       if (ItinData) {
565         formItineraryOperandCycleString(ItinData, ItinOperandCycleString,
566                                         NOperandCycles);
567 
568         formItineraryBypassString(std::string(Name), ItinData, ItinBypassString,
569                                   NOperandCycles);
570       }
571 
572       // Check to see if stage already exists and create if it doesn't
573       uint16_t FindStage = 0;
574       if (NStages > 0) {
575         FindStage = ItinStageMap[ItinStageString];
576         if (FindStage == 0) {
577           // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
578           StageTable += ItinStageString + ", // " + itostr(StageCount);
579           if (NStages > 1)
580             StageTable += "-" + itostr(StageCount + NStages - 1);
581           StageTable += "\n";
582           // Record Itin class number.
583           ItinStageMap[ItinStageString] = FindStage = StageCount;
584           StageCount += NStages;
585         }
586       }
587 
588       // Check to see if operand cycle already exists and create if it doesn't
589       uint16_t FindOperandCycle = 0;
590       if (NOperandCycles > 0) {
591         std::string ItinOperandString =
592             ItinOperandCycleString + ItinBypassString;
593         FindOperandCycle = ItinOperandMap[ItinOperandString];
594         if (FindOperandCycle == 0) {
595           // Emit as  cycle, // index
596           OperandCycleTable += ItinOperandCycleString + ", // ";
597           std::string OperandIdxComment = itostr(OperandCycleCount);
598           if (NOperandCycles > 1)
599             OperandIdxComment +=
600                 "-" + itostr(OperandCycleCount + NOperandCycles - 1);
601           OperandCycleTable += OperandIdxComment + "\n";
602           // Record Itin class number.
603           ItinOperandMap[ItinOperandCycleString] = FindOperandCycle =
604               OperandCycleCount;
605           // Emit as bypass, // index
606           BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
607           OperandCycleCount += NOperandCycles;
608         }
609       }
610 
611       // Set up itinerary as location and location + stage count
612       int16_t NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
613       InstrItinerary Intinerary = {
614           NumUOps,
615           FindStage,
616           uint16_t(FindStage + NStages),
617           FindOperandCycle,
618           uint16_t(FindOperandCycle + NOperandCycles),
619       };
620 
621       // Inject - empty slots will be 0, 0
622       ItinList[SchedClassIdx] = Intinerary;
623     }
624   }
625 
626   // Closing stage
627   StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
628   StageTable += "};\n";
629 
630   // Closing operand cycles
631   OperandCycleTable += "  0 // End operand cycles\n";
632   OperandCycleTable += "};\n";
633 
634   BypassTable += " 0 // End bypass tables\n";
635   BypassTable += "};\n";
636 
637   // Emit tables.
638   OS << StageTable;
639   OS << OperandCycleTable;
640   OS << BypassTable;
641 }
642 
643 //
644 // EmitProcessorData - Generate data for processor itineraries that were
645 // computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
646 // Itineraries for each processor. The Itinerary lists are indexed on
647 // CodeGenSchedClass::Index.
648 //
649 void SubtargetEmitter::emitItineraries(
650     raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
651   // Multiple processor models may share an itinerary record. Emit it once.
652   SmallPtrSet<const Record *, 8> ItinsDefSet;
653 
654   // For each processor's machine model
655   std::vector<std::vector<InstrItinerary>>::iterator ProcItinListsIter =
656       ProcItinLists.begin();
657   for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
658                                     PE = SchedModels.procModelEnd();
659        PI != PE; ++PI, ++ProcItinListsIter) {
660 
661     const Record *ItinsDef = PI->ItinsDef;
662     if (!ItinsDefSet.insert(ItinsDef).second)
663       continue;
664 
665     // Get the itinerary list for the processor.
666     assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
667     std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
668 
669     // Empty itineraries aren't referenced anywhere in the tablegen output
670     // so don't emit them.
671     if (ItinList.empty())
672       continue;
673 
674     OS << "\n";
675     OS << "static const llvm::InstrItinerary ";
676 
677     // Begin processor itinerary table
678     OS << ItinsDef->getName() << "[] = {\n";
679 
680     // For each itinerary class in CodeGenSchedClass::Index order.
681     for (unsigned J = 0, M = ItinList.size(); J < M; ++J) {
682       InstrItinerary &Intinerary = ItinList[J];
683 
684       // Emit Itinerary in the form of
685       // { firstStage, lastStage, firstCycle, lastCycle } // index
686       OS << "  { " << Intinerary.NumMicroOps << ", " << Intinerary.FirstStage
687          << ", " << Intinerary.LastStage << ", " << Intinerary.FirstOperandCycle
688          << ", " << Intinerary.LastOperandCycle << " }"
689          << ", // " << J << " " << SchedModels.getSchedClass(J).Name << "\n";
690     }
691     // End processor itinerary table
692     OS << "  { 0, uint16_t(~0U), uint16_t(~0U), uint16_t(~0U), uint16_t(~0U) }"
693           "// end marker\n";
694     OS << "};\n";
695   }
696 }
697 
698 // Emit either the value defined in the TableGen Record, or the default
699 // value defined in the C++ header. The Record is null if the processor does not
700 // define a model.
701 void SubtargetEmitter::emitProcessorProp(raw_ostream &OS, const Record *R,
702                                          StringRef Name, char Separator) {
703   OS << "  ";
704   int V = R ? R->getValueAsInt(Name) : -1;
705   if (V >= 0)
706     OS << V << Separator << " // " << Name;
707   else
708     OS << "MCSchedModel::Default" << Name << Separator;
709   OS << '\n';
710 }
711 
712 void SubtargetEmitter::emitProcessorResourceSubUnits(
713     const CodeGenProcModel &ProcModel, raw_ostream &OS) {
714   OS << "\nstatic const unsigned " << ProcModel.ModelName
715      << "ProcResourceSubUnits[] = {\n"
716      << "  0,  // Invalid\n";
717 
718   for (unsigned I = 0, E = ProcModel.ProcResourceDefs.size(); I < E; ++I) {
719     const Record *PRDef = ProcModel.ProcResourceDefs[I];
720     if (!PRDef->isSubClassOf("ProcResGroup"))
721       continue;
722     for (const Record *RUDef : PRDef->getValueAsListOfDefs("Resources")) {
723       const Record *RU =
724           SchedModels.findProcResUnits(RUDef, ProcModel, PRDef->getLoc());
725       for (unsigned J = 0; J < RU->getValueAsInt("NumUnits"); ++J) {
726         OS << "  " << ProcModel.getProcResourceIdx(RU) << ", ";
727       }
728     }
729     OS << "  // " << PRDef->getName() << "\n";
730   }
731   OS << "};\n";
732 }
733 
734 static void emitRetireControlUnitInfo(const CodeGenProcModel &ProcModel,
735                                       raw_ostream &OS) {
736   int64_t ReorderBufferSize = 0, MaxRetirePerCycle = 0;
737   if (const Record *RCU = ProcModel.RetireControlUnit) {
738     ReorderBufferSize =
739         std::max(ReorderBufferSize, RCU->getValueAsInt("ReorderBufferSize"));
740     MaxRetirePerCycle =
741         std::max(MaxRetirePerCycle, RCU->getValueAsInt("MaxRetirePerCycle"));
742   }
743 
744   OS << ReorderBufferSize << ", // ReorderBufferSize\n  ";
745   OS << MaxRetirePerCycle << ", // MaxRetirePerCycle\n  ";
746 }
747 
748 static void emitRegisterFileInfo(const CodeGenProcModel &ProcModel,
749                                  unsigned NumRegisterFiles,
750                                  unsigned NumCostEntries, raw_ostream &OS) {
751   if (NumRegisterFiles)
752     OS << ProcModel.ModelName << "RegisterFiles,\n  " << (1 + NumRegisterFiles);
753   else
754     OS << "nullptr,\n  0";
755 
756   OS << ", // Number of register files.\n  ";
757   if (NumCostEntries)
758     OS << ProcModel.ModelName << "RegisterCosts,\n  ";
759   else
760     OS << "nullptr,\n  ";
761   OS << NumCostEntries << ", // Number of register cost entries.\n";
762 }
763 
764 unsigned
765 SubtargetEmitter::emitRegisterFileTables(const CodeGenProcModel &ProcModel,
766                                          raw_ostream &OS) {
767   if (llvm::all_of(ProcModel.RegisterFiles, [](const CodeGenRegisterFile &RF) {
768         return RF.hasDefaultCosts();
769       }))
770     return 0;
771 
772   // Print the RegisterCost table first.
773   OS << "\n// {RegisterClassID, Register Cost, AllowMoveElimination }\n";
774   OS << "static const llvm::MCRegisterCostEntry " << ProcModel.ModelName
775      << "RegisterCosts"
776      << "[] = {\n";
777 
778   for (const CodeGenRegisterFile &RF : ProcModel.RegisterFiles) {
779     // Skip register files with a default cost table.
780     if (RF.hasDefaultCosts())
781       continue;
782     // Add entries to the cost table.
783     for (const CodeGenRegisterCost &RC : RF.Costs) {
784       OS << "  { ";
785       const Record *Rec = RC.RCDef;
786       if (Rec->getValue("Namespace"))
787         OS << Rec->getValueAsString("Namespace") << "::";
788       OS << Rec->getName() << "RegClassID, " << RC.Cost << ", "
789          << RC.AllowMoveElimination << "},\n";
790     }
791   }
792   OS << "};\n";
793 
794   // Now generate a table with register file info.
795   OS << "\n // {Name, #PhysRegs, #CostEntries, IndexToCostTbl, "
796      << "MaxMovesEliminatedPerCycle, AllowZeroMoveEliminationOnly }\n";
797   OS << "static const llvm::MCRegisterFileDesc " << ProcModel.ModelName
798      << "RegisterFiles"
799      << "[] = {\n"
800      << "  { \"InvalidRegisterFile\", 0, 0, 0, 0, 0 },\n";
801   unsigned CostTblIndex = 0;
802 
803   for (const CodeGenRegisterFile &RD : ProcModel.RegisterFiles) {
804     OS << "  { ";
805     OS << '"' << RD.Name << '"' << ", " << RD.NumPhysRegs << ", ";
806     unsigned NumCostEntries = RD.Costs.size();
807     OS << NumCostEntries << ", " << CostTblIndex << ", "
808        << RD.MaxMovesEliminatedPerCycle << ", "
809        << RD.AllowZeroMoveEliminationOnly << "},\n";
810     CostTblIndex += NumCostEntries;
811   }
812   OS << "};\n";
813 
814   return CostTblIndex;
815 }
816 
817 void SubtargetEmitter::emitLoadStoreQueueInfo(const CodeGenProcModel &ProcModel,
818                                               raw_ostream &OS) {
819   unsigned QueueID = 0;
820   if (ProcModel.LoadQueue) {
821     const Record *Queue = ProcModel.LoadQueue->getValueAsDef("QueueDescriptor");
822     QueueID = 1 + std::distance(ProcModel.ProcResourceDefs.begin(),
823                                 find(ProcModel.ProcResourceDefs, Queue));
824   }
825   OS << "  " << QueueID << ", // Resource Descriptor for the Load Queue\n";
826 
827   QueueID = 0;
828   if (ProcModel.StoreQueue) {
829     const Record *Queue =
830         ProcModel.StoreQueue->getValueAsDef("QueueDescriptor");
831     QueueID = 1 + std::distance(ProcModel.ProcResourceDefs.begin(),
832                                 find(ProcModel.ProcResourceDefs, Queue));
833   }
834   OS << "  " << QueueID << ", // Resource Descriptor for the Store Queue\n";
835 }
836 
837 void SubtargetEmitter::emitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
838                                               raw_ostream &OS) {
839   // Generate a table of register file descriptors (one entry per each user
840   // defined register file), and a table of register costs.
841   unsigned NumCostEntries = emitRegisterFileTables(ProcModel, OS);
842 
843   // Now generate a table for the extra processor info.
844   OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
845      << "ExtraInfo = {\n  ";
846 
847   // Add information related to the retire control unit.
848   emitRetireControlUnitInfo(ProcModel, OS);
849 
850   // Add information related to the register files (i.e. where to find register
851   // file descriptors and register costs).
852   emitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
853                        NumCostEntries, OS);
854 
855   // Add information about load/store queues.
856   emitLoadStoreQueueInfo(ProcModel, OS);
857 
858   OS << "};\n";
859 }
860 
861 void SubtargetEmitter::emitProcessorResources(const CodeGenProcModel &ProcModel,
862                                               raw_ostream &OS) {
863   emitProcessorResourceSubUnits(ProcModel, OS);
864 
865   OS << "\n// {Name, NumUnits, SuperIdx, BufferSize, SubUnitsIdxBegin}\n";
866   OS << "static const llvm::MCProcResourceDesc " << ProcModel.ModelName
867      << "ProcResources"
868      << "[] = {\n"
869      << "  {\"InvalidUnit\", 0, 0, 0, 0},\n";
870 
871   unsigned SubUnitsOffset = 1;
872   for (unsigned I = 0, E = ProcModel.ProcResourceDefs.size(); I < E; ++I) {
873     const Record *PRDef = ProcModel.ProcResourceDefs[I];
874 
875     const Record *SuperDef = nullptr;
876     unsigned SuperIdx = 0;
877     unsigned NumUnits = 0;
878     const unsigned SubUnitsBeginOffset = SubUnitsOffset;
879     int BufferSize = PRDef->getValueAsInt("BufferSize");
880     if (PRDef->isSubClassOf("ProcResGroup")) {
881       for (const Record *RU : PRDef->getValueAsListOfDefs("Resources")) {
882         NumUnits += RU->getValueAsInt("NumUnits");
883         SubUnitsOffset += RU->getValueAsInt("NumUnits");
884       }
885     } else {
886       // Find the SuperIdx
887       if (PRDef->getValueInit("Super")->isComplete()) {
888         SuperDef = SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"),
889                                                 ProcModel, PRDef->getLoc());
890         SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
891       }
892       NumUnits = PRDef->getValueAsInt("NumUnits");
893     }
894     // Emit the ProcResourceDesc
895     OS << "  {\"" << PRDef->getName() << "\", ";
896     if (PRDef->getName().size() < 15)
897       OS.indent(15 - PRDef->getName().size());
898     OS << NumUnits << ", " << SuperIdx << ", " << BufferSize << ", ";
899     if (SubUnitsBeginOffset != SubUnitsOffset) {
900       OS << ProcModel.ModelName << "ProcResourceSubUnits + "
901          << SubUnitsBeginOffset;
902     } else {
903       OS << "nullptr";
904     }
905     OS << "}, // #" << I + 1;
906     if (SuperDef)
907       OS << ", Super=" << SuperDef->getName();
908     OS << "\n";
909   }
910   OS << "};\n";
911 }
912 
913 // Find the WriteRes Record that defines processor resources for this
914 // SchedWrite.
915 const Record *
916 SubtargetEmitter::findWriteResources(const CodeGenSchedRW &SchedWrite,
917                                      const CodeGenProcModel &ProcModel) {
918 
919   // Check if the SchedWrite is already subtarget-specific and directly
920   // specifies a set of processor resources.
921   if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
922     return SchedWrite.TheDef;
923 
924   const Record *AliasDef = nullptr;
925   for (const Record *A : SchedWrite.Aliases) {
926     const CodeGenSchedRW &AliasRW =
927         SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
928     if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
929       const Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
930       if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
931         continue;
932     }
933     if (AliasDef)
934       PrintFatalError(AliasRW.TheDef->getLoc(),
935                       "Multiple aliases "
936                       "defined for processor " +
937                           ProcModel.ModelName +
938                           " Ensure only one SchedAlias exists per RW.");
939     AliasDef = AliasRW.TheDef;
940   }
941   if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
942     return AliasDef;
943 
944   // Check this processor's list of write resources.
945   const Record *ResDef = nullptr;
946 
947   auto I = ProcModel.WriteResMap.find(SchedWrite.TheDef);
948   if (I != ProcModel.WriteResMap.end())
949     ResDef = I->second;
950 
951   if (AliasDef) {
952     I = ProcModel.WriteResMap.find(AliasDef);
953     if (I != ProcModel.WriteResMap.end()) {
954       if (ResDef)
955         PrintFatalError(I->second->getLoc(),
956                         "Resources are defined for both SchedWrite and its "
957                         "alias on processor " +
958                             ProcModel.ModelName);
959       ResDef = I->second;
960     }
961   }
962 
963   // TODO: If ProcModel has a base model (previous generation processor),
964   // then call FindWriteResources recursively with that model here.
965   if (!ResDef) {
966     PrintFatalError(ProcModel.ModelDef->getLoc(),
967                     Twine("Processor does not define resources for ") +
968                         SchedWrite.TheDef->getName());
969   }
970   return ResDef;
971 }
972 
973 /// Find the ReadAdvance record for the given SchedRead on this processor or
974 /// return NULL.
975 const Record *
976 SubtargetEmitter::findReadAdvance(const CodeGenSchedRW &SchedRead,
977                                   const CodeGenProcModel &ProcModel) {
978   // Check for SchedReads that directly specify a ReadAdvance.
979   if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
980     return SchedRead.TheDef;
981 
982   // Check this processor's list of aliases for SchedRead.
983   const Record *AliasDef = nullptr;
984   for (const Record *A : SchedRead.Aliases) {
985     const CodeGenSchedRW &AliasRW =
986         SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
987     if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
988       const Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
989       if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
990         continue;
991     }
992     if (AliasDef)
993       PrintFatalError(AliasRW.TheDef->getLoc(),
994                       "Multiple aliases "
995                       "defined for processor " +
996                           ProcModel.ModelName +
997                           " Ensure only one SchedAlias exists per RW.");
998     AliasDef = AliasRW.TheDef;
999   }
1000   if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
1001     return AliasDef;
1002 
1003   // Check this processor's ReadAdvanceList.
1004   const Record *ResDef = nullptr;
1005 
1006   auto I = ProcModel.ReadAdvanceMap.find(SchedRead.TheDef);
1007   if (I != ProcModel.ReadAdvanceMap.end())
1008     ResDef = I->second;
1009 
1010   if (AliasDef) {
1011     I = ProcModel.ReadAdvanceMap.find(AliasDef);
1012     if (I != ProcModel.ReadAdvanceMap.end()) {
1013       if (ResDef)
1014         PrintFatalError(
1015             I->second->getLoc(),
1016             "Resources are defined for both SchedRead and its alias on "
1017             "processor " +
1018                 ProcModel.ModelName);
1019       ResDef = I->second;
1020     }
1021   }
1022 
1023   // TODO: If ProcModel has a base model (previous generation processor),
1024   // then call FindReadAdvance recursively with that model here.
1025   if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
1026     PrintFatalError(ProcModel.ModelDef->getLoc(),
1027                     Twine("Processor does not define resources for ") +
1028                         SchedRead.TheDef->getName());
1029   }
1030   return ResDef;
1031 }
1032 
1033 // Expand an explicit list of processor resources into a full list of implied
1034 // resource groups and super resources that cover them.
1035 void SubtargetEmitter::expandProcResources(
1036     ConstRecVec &PRVec, std::vector<int64_t> &ReleaseAtCycles,
1037     std::vector<int64_t> &AcquireAtCycles, const CodeGenProcModel &PM) {
1038   assert(PRVec.size() == ReleaseAtCycles.size() && "failed precondition");
1039   for (unsigned I = 0, E = PRVec.size(); I != E; ++I) {
1040     const Record *PRDef = PRVec[I];
1041     ConstRecVec SubResources;
1042     if (PRDef->isSubClassOf("ProcResGroup"))
1043       SubResources = PRDef->getValueAsListOfDefs("Resources");
1044     else {
1045       SubResources.push_back(PRDef);
1046       PRDef = SchedModels.findProcResUnits(PRDef, PM, PRDef->getLoc());
1047       for (const Record *SubDef = PRDef;
1048            SubDef->getValueInit("Super")->isComplete();) {
1049         if (SubDef->isSubClassOf("ProcResGroup")) {
1050           // Disallow this for simplicitly.
1051           PrintFatalError(SubDef->getLoc(), "Processor resource group "
1052                                             " cannot be a super resources.");
1053         }
1054         const Record *SuperDef = SchedModels.findProcResUnits(
1055             SubDef->getValueAsDef("Super"), PM, SubDef->getLoc());
1056         PRVec.push_back(SuperDef);
1057         ReleaseAtCycles.push_back(ReleaseAtCycles[I]);
1058         AcquireAtCycles.push_back(AcquireAtCycles[I]);
1059         SubDef = SuperDef;
1060       }
1061     }
1062     for (const Record *PR : PM.ProcResourceDefs) {
1063       if (PR == PRDef || !PR->isSubClassOf("ProcResGroup"))
1064         continue;
1065       ConstRecVec SuperResources = PR->getValueAsListOfDefs("Resources");
1066       ConstRecIter SubI = SubResources.begin(), SubE = SubResources.end();
1067       for (; SubI != SubE; ++SubI) {
1068         if (!is_contained(SuperResources, *SubI)) {
1069           break;
1070         }
1071       }
1072       if (SubI == SubE) {
1073         PRVec.push_back(PR);
1074         ReleaseAtCycles.push_back(ReleaseAtCycles[I]);
1075         AcquireAtCycles.push_back(AcquireAtCycles[I]);
1076       }
1077     }
1078   }
1079 }
1080 
1081 // Generate the SchedClass table for this processor and update global
1082 // tables. Must be called for each processor in order.
1083 void SubtargetEmitter::genSchedClassTables(const CodeGenProcModel &ProcModel,
1084                                            SchedClassTables &SchedTables) {
1085   std::vector<MCSchedClassDesc> &SCTab =
1086       SchedTables.ProcSchedClasses.emplace_back();
1087   if (!ProcModel.hasInstrSchedModel())
1088     return;
1089 
1090   LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (GenSchedClassTables) +++\n");
1091   for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
1092     LLVM_DEBUG(SC.dump(&SchedModels));
1093 
1094     MCSchedClassDesc &SCDesc = SCTab.emplace_back();
1095     // SCDesc.Name is guarded by NDEBUG
1096     SCDesc.NumMicroOps = 0;
1097     SCDesc.BeginGroup = false;
1098     SCDesc.EndGroup = false;
1099     SCDesc.RetireOOO = false;
1100     SCDesc.WriteProcResIdx = 0;
1101     SCDesc.WriteLatencyIdx = 0;
1102     SCDesc.ReadAdvanceIdx = 0;
1103 
1104     // A Variant SchedClass has no resources of its own.
1105     bool HasVariants = false;
1106     for (const CodeGenSchedTransition &CGT : SC.Transitions) {
1107       if (CGT.ProcIndex == ProcModel.Index) {
1108         HasVariants = true;
1109         break;
1110       }
1111     }
1112     if (HasVariants) {
1113       SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
1114       continue;
1115     }
1116 
1117     // Determine if the SchedClass is actually reachable on this processor. If
1118     // not don't try to locate the processor resources, it will fail.
1119     // If ProcIndices contains 0, this class applies to all processors.
1120     assert(!SC.ProcIndices.empty() && "expect at least one procidx");
1121     if (SC.ProcIndices[0] != 0) {
1122       if (!is_contained(SC.ProcIndices, ProcModel.Index))
1123         continue;
1124     }
1125     IdxVec Writes = SC.Writes;
1126     IdxVec Reads = SC.Reads;
1127     if (!SC.InstRWs.empty()) {
1128       // This class has a default ReadWrite list which can be overridden by
1129       // InstRW definitions.
1130       const Record *RWDef = nullptr;
1131       for (const Record *RW : SC.InstRWs) {
1132         const Record *RWModelDef = RW->getValueAsDef("SchedModel");
1133         if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
1134           RWDef = RW;
1135           break;
1136         }
1137       }
1138       if (RWDef) {
1139         Writes.clear();
1140         Reads.clear();
1141         SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
1142                             Writes, Reads);
1143       }
1144     }
1145     if (Writes.empty()) {
1146       // Check this processor's itinerary class resources.
1147       for (const Record *I : ProcModel.ItinRWDefs) {
1148         ConstRecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses");
1149         if (is_contained(Matched, SC.ItinClassDef)) {
1150           SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"),
1151                               Writes, Reads);
1152           break;
1153         }
1154       }
1155       if (Writes.empty()) {
1156         LLVM_DEBUG(dbgs() << ProcModel.ModelName
1157                           << " does not have resources for class " << SC.Name
1158                           << '\n');
1159         SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
1160       }
1161     }
1162     // Sum resources across all operand writes.
1163     std::vector<MCWriteProcResEntry> WriteProcResources;
1164     std::vector<MCWriteLatencyEntry> WriteLatencies;
1165     std::vector<std::string> WriterNames;
1166     std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
1167     for (unsigned W : Writes) {
1168       IdxVec WriteSeq;
1169       SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false, ProcModel);
1170 
1171       // For each operand, create a latency entry.
1172       MCWriteLatencyEntry WLEntry;
1173       WLEntry.Cycles = 0;
1174       unsigned WriteID = WriteSeq.back();
1175       WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
1176       // If this Write is not referenced by a ReadAdvance, don't distinguish it
1177       // from other WriteLatency entries.
1178       if (!ProcModel.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef))
1179         WriteID = 0;
1180       WLEntry.WriteResourceID = WriteID;
1181 
1182       for (unsigned WS : WriteSeq) {
1183         const Record *WriteRes =
1184             findWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
1185 
1186         // Mark the parent class as invalid for unsupported write types.
1187         if (WriteRes->getValueAsBit("Unsupported")) {
1188           SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
1189           break;
1190         }
1191         WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
1192         SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
1193         SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
1194         SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
1195         SCDesc.BeginGroup |= WriteRes->getValueAsBit("SingleIssue");
1196         SCDesc.EndGroup |= WriteRes->getValueAsBit("SingleIssue");
1197         SCDesc.RetireOOO |= WriteRes->getValueAsBit("RetireOOO");
1198 
1199         // Create an entry for each ProcResource listed in WriteRes.
1200         ConstRecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
1201         std::vector<int64_t> ReleaseAtCycles =
1202             WriteRes->getValueAsListOfInts("ReleaseAtCycles");
1203 
1204         std::vector<int64_t> AcquireAtCycles =
1205             WriteRes->getValueAsListOfInts("AcquireAtCycles");
1206 
1207         // Check consistency of the two vectors carrying the start and
1208         // stop cycles of the resources.
1209         if (!ReleaseAtCycles.empty() &&
1210             ReleaseAtCycles.size() != PRVec.size()) {
1211           // If ReleaseAtCycles is provided, check consistency.
1212           PrintFatalError(
1213               WriteRes->getLoc(),
1214               Twine("Inconsistent release at cycles: size(ReleaseAtCycles) != "
1215                     "size(ProcResources): ")
1216                   .concat(Twine(PRVec.size()))
1217                   .concat(" vs ")
1218                   .concat(Twine(ReleaseAtCycles.size())));
1219         }
1220 
1221         if (!AcquireAtCycles.empty() &&
1222             AcquireAtCycles.size() != PRVec.size()) {
1223           PrintFatalError(
1224               WriteRes->getLoc(),
1225               Twine("Inconsistent resource cycles: size(AcquireAtCycles) != "
1226                     "size(ProcResources): ")
1227                   .concat(Twine(AcquireAtCycles.size()))
1228                   .concat(" vs ")
1229                   .concat(Twine(PRVec.size())));
1230         }
1231 
1232         if (ReleaseAtCycles.empty()) {
1233           // If ReleaseAtCycles is not provided, default to one cycle
1234           // per resource.
1235           ReleaseAtCycles.resize(PRVec.size(), 1);
1236         }
1237 
1238         if (AcquireAtCycles.empty()) {
1239           // If AcquireAtCycles is not provided, reserve the resource
1240           // starting from cycle 0.
1241           AcquireAtCycles.resize(PRVec.size(), 0);
1242         }
1243 
1244         assert(AcquireAtCycles.size() == ReleaseAtCycles.size());
1245 
1246         expandProcResources(PRVec, ReleaseAtCycles, AcquireAtCycles, ProcModel);
1247         assert(AcquireAtCycles.size() == ReleaseAtCycles.size());
1248 
1249         for (unsigned PRIdx = 0, PREnd = PRVec.size(); PRIdx != PREnd;
1250              ++PRIdx) {
1251           MCWriteProcResEntry WPREntry;
1252           WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
1253           assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
1254           WPREntry.ReleaseAtCycle = ReleaseAtCycles[PRIdx];
1255           WPREntry.AcquireAtCycle = AcquireAtCycles[PRIdx];
1256           if (AcquireAtCycles[PRIdx] > ReleaseAtCycles[PRIdx]) {
1257             PrintFatalError(
1258                 WriteRes->getLoc(),
1259                 Twine("Inconsistent resource cycles: AcquireAtCycles "
1260                       "< ReleaseAtCycles must hold."));
1261           }
1262           if (AcquireAtCycles[PRIdx] < 0) {
1263             PrintFatalError(WriteRes->getLoc(),
1264                             Twine("Invalid value: AcquireAtCycle "
1265                                   "must be a non-negative value."));
1266           }
1267           // If this resource is already used in this sequence, add the current
1268           // entry's cycles so that the same resource appears to be used
1269           // serially, rather than multiple parallel uses. This is important for
1270           // in-order machine where the resource consumption is a hazard.
1271           unsigned WPRIdx = 0, WPREnd = WriteProcResources.size();
1272           for (; WPRIdx != WPREnd; ++WPRIdx) {
1273             if (WriteProcResources[WPRIdx].ProcResourceIdx ==
1274                 WPREntry.ProcResourceIdx) {
1275               // TODO: multiple use of the same resources would
1276               // require either 1. thinking of how to handle multiple
1277               // intervals for the same resource in
1278               // `<Target>WriteProcResTable` (see
1279               // `SubtargetEmitter::EmitSchedClassTables`), or
1280               // 2. thinking how to merge multiple intervals into a
1281               // single interval.
1282               assert(WPREntry.AcquireAtCycle == 0 &&
1283                      "multiple use ofthe same resource is not yet handled");
1284               WriteProcResources[WPRIdx].ReleaseAtCycle +=
1285                   WPREntry.ReleaseAtCycle;
1286               break;
1287             }
1288           }
1289           if (WPRIdx == WPREnd)
1290             WriteProcResources.push_back(WPREntry);
1291         }
1292       }
1293       WriteLatencies.push_back(WLEntry);
1294     }
1295     // Create an entry for each operand Read in this SchedClass.
1296     // Entries must be sorted first by UseIdx then by WriteResourceID.
1297     for (unsigned UseIdx = 0, EndIdx = Reads.size(); UseIdx != EndIdx;
1298          ++UseIdx) {
1299       const Record *ReadAdvance =
1300           findReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
1301       if (!ReadAdvance)
1302         continue;
1303 
1304       // Mark the parent class as invalid for unsupported write types.
1305       if (ReadAdvance->getValueAsBit("Unsupported")) {
1306         SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
1307         break;
1308       }
1309       ConstRecVec ValidWrites =
1310           ReadAdvance->getValueAsListOfDefs("ValidWrites");
1311       IdxVec WriteIDs;
1312       if (ValidWrites.empty())
1313         WriteIDs.push_back(0);
1314       else {
1315         for (const Record *VW : ValidWrites) {
1316           unsigned WriteID = SchedModels.getSchedRWIdx(VW, /*IsRead=*/false);
1317           assert(WriteID != 0 &&
1318                  "Expected a valid SchedRW in the list of ValidWrites");
1319           WriteIDs.push_back(WriteID);
1320         }
1321       }
1322       llvm::sort(WriteIDs);
1323       for (unsigned W : WriteIDs) {
1324         MCReadAdvanceEntry RAEntry;
1325         RAEntry.UseIdx = UseIdx;
1326         RAEntry.WriteResourceID = W;
1327         RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
1328         ReadAdvanceEntries.push_back(RAEntry);
1329       }
1330     }
1331     if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
1332       WriteProcResources.clear();
1333       WriteLatencies.clear();
1334       ReadAdvanceEntries.clear();
1335     }
1336     // Add the information for this SchedClass to the global tables using basic
1337     // compression.
1338     //
1339     // WritePrecRes entries are sorted by ProcResIdx.
1340     llvm::sort(WriteProcResources, LessWriteProcResources());
1341 
1342     SCDesc.NumWriteProcResEntries = WriteProcResources.size();
1343     std::vector<MCWriteProcResEntry>::iterator WPRPos =
1344         std::search(SchedTables.WriteProcResources.begin(),
1345                     SchedTables.WriteProcResources.end(),
1346                     WriteProcResources.begin(), WriteProcResources.end());
1347     if (WPRPos != SchedTables.WriteProcResources.end())
1348       SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
1349     else {
1350       SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
1351       SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
1352                                             WriteProcResources.end());
1353     }
1354     // Latency entries must remain in operand order.
1355     SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
1356     std::vector<MCWriteLatencyEntry>::iterator WLPos = std::search(
1357         SchedTables.WriteLatencies.begin(), SchedTables.WriteLatencies.end(),
1358         WriteLatencies.begin(), WriteLatencies.end());
1359     if (WLPos != SchedTables.WriteLatencies.end()) {
1360       unsigned Idx = WLPos - SchedTables.WriteLatencies.begin();
1361       SCDesc.WriteLatencyIdx = Idx;
1362       for (unsigned I = 0, E = WriteLatencies.size(); I < E; ++I)
1363         if (SchedTables.WriterNames[Idx + I].find(WriterNames[I]) ==
1364             std::string::npos) {
1365           SchedTables.WriterNames[Idx + I] += std::string("_") + WriterNames[I];
1366         }
1367     } else {
1368       SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
1369       llvm::append_range(SchedTables.WriteLatencies, WriteLatencies);
1370       llvm::append_range(SchedTables.WriterNames, WriterNames);
1371     }
1372     // ReadAdvanceEntries must remain in operand order.
1373     SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
1374     std::vector<MCReadAdvanceEntry>::iterator RAPos =
1375         std::search(SchedTables.ReadAdvanceEntries.begin(),
1376                     SchedTables.ReadAdvanceEntries.end(),
1377                     ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
1378     if (RAPos != SchedTables.ReadAdvanceEntries.end())
1379       SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
1380     else {
1381       SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
1382       llvm::append_range(SchedTables.ReadAdvanceEntries, ReadAdvanceEntries);
1383     }
1384   }
1385 }
1386 
1387 // Emit SchedClass tables for all processors and associated global tables.
1388 void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
1389                                             raw_ostream &OS) {
1390   // Emit global WriteProcResTable.
1391   OS << "\n// {ProcResourceIdx, ReleaseAtCycle, AcquireAtCycle}\n"
1392      << "extern const llvm::MCWriteProcResEntry " << Target
1393      << "WriteProcResTable[] = {\n"
1394      << "  { 0,  0,  0 }, // Invalid\n";
1395   for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
1396        WPRIdx != WPREnd; ++WPRIdx) {
1397     MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
1398     OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
1399        << format("%2d", WPREntry.ReleaseAtCycle) << ",  "
1400        << format("%2d", WPREntry.AcquireAtCycle) << "}";
1401     if (WPRIdx + 1 < WPREnd)
1402       OS << ',';
1403     OS << " // #" << WPRIdx << '\n';
1404   }
1405   OS << "}; // " << Target << "WriteProcResTable\n";
1406 
1407   // Emit global WriteLatencyTable.
1408   OS << "\n// {Cycles, WriteResourceID}\n"
1409      << "extern const llvm::MCWriteLatencyEntry " << Target
1410      << "WriteLatencyTable[] = {\n"
1411      << "  { 0,  0}, // Invalid\n";
1412   for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
1413        WLIdx != WLEnd; ++WLIdx) {
1414     MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
1415     OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
1416        << format("%2d", WLEntry.WriteResourceID) << "}";
1417     if (WLIdx + 1 < WLEnd)
1418       OS << ',';
1419     OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
1420   }
1421   OS << "}; // " << Target << "WriteLatencyTable\n";
1422 
1423   // Emit global ReadAdvanceTable.
1424   OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
1425      << "extern const llvm::MCReadAdvanceEntry " << Target
1426      << "ReadAdvanceTable[] = {\n"
1427      << "  {0,  0,  0}, // Invalid\n";
1428   for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
1429        RAIdx != RAEnd; ++RAIdx) {
1430     MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
1431     OS << "  {" << RAEntry.UseIdx << ", "
1432        << format("%2d", RAEntry.WriteResourceID) << ", "
1433        << format("%2d", RAEntry.Cycles) << "}";
1434     if (RAIdx + 1 < RAEnd)
1435       OS << ',';
1436     OS << " // #" << RAIdx << '\n';
1437   }
1438   OS << "}; // " << Target << "ReadAdvanceTable\n";
1439 
1440   // Emit a SchedClass table for each processor.
1441   for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1442                                     PE = SchedModels.procModelEnd();
1443        PI != PE; ++PI) {
1444     if (!PI->hasInstrSchedModel())
1445       continue;
1446 
1447     std::vector<MCSchedClassDesc> &SCTab =
1448         SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
1449 
1450     OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup, RetireOOO,"
1451        << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
1452     OS << "static const llvm::MCSchedClassDesc " << PI->ModelName
1453        << "SchedClasses[] = {\n";
1454 
1455     // The first class is always invalid. We no way to distinguish it except by
1456     // name and position.
1457     assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" &&
1458            "invalid class not first");
1459     OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
1460        << MCSchedClassDesc::InvalidNumMicroOps
1461        << ", false, false, false, 0, 0,  0, 0,  0, 0},\n";
1462 
1463     for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
1464       MCSchedClassDesc &MCDesc = SCTab[SCIdx];
1465       const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
1466       OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
1467       if (SchedClass.Name.size() < 18)
1468         OS.indent(18 - SchedClass.Name.size());
1469       OS << MCDesc.NumMicroOps << ", " << (MCDesc.BeginGroup ? "true" : "false")
1470          << ", " << (MCDesc.EndGroup ? "true" : "false") << ", "
1471          << (MCDesc.RetireOOO ? "true" : "false") << ", "
1472          << format("%2d", MCDesc.WriteProcResIdx) << ", "
1473          << MCDesc.NumWriteProcResEntries << ", "
1474          << format("%2d", MCDesc.WriteLatencyIdx) << ", "
1475          << MCDesc.NumWriteLatencyEntries << ", "
1476          << format("%2d", MCDesc.ReadAdvanceIdx) << ", "
1477          << MCDesc.NumReadAdvanceEntries << "}, // #" << SCIdx << '\n';
1478     }
1479     OS << "}; // " << PI->ModelName << "SchedClasses\n";
1480   }
1481 }
1482 
1483 void SubtargetEmitter::emitProcessorModels(raw_ostream &OS) {
1484   // For each processor model.
1485   for (const CodeGenProcModel &PM : SchedModels.procModels()) {
1486     // Emit extra processor info if available.
1487     if (PM.hasExtraProcessorInfo())
1488       emitExtraProcessorInfo(PM, OS);
1489     // Emit processor resource table.
1490     if (PM.hasInstrSchedModel())
1491       emitProcessorResources(PM, OS);
1492     else if (!PM.ProcResourceDefs.empty())
1493       PrintFatalError(PM.ModelDef->getLoc(),
1494                       "SchedMachineModel defines "
1495                       "ProcResources without defining WriteRes SchedWriteRes");
1496 
1497     // Begin processor itinerary properties
1498     OS << "\n";
1499     OS << "static const llvm::MCSchedModel " << PM.ModelName << " = {\n";
1500     emitProcessorProp(OS, PM.ModelDef, "IssueWidth", ',');
1501     emitProcessorProp(OS, PM.ModelDef, "MicroOpBufferSize", ',');
1502     emitProcessorProp(OS, PM.ModelDef, "LoopMicroOpBufferSize", ',');
1503     emitProcessorProp(OS, PM.ModelDef, "LoadLatency", ',');
1504     emitProcessorProp(OS, PM.ModelDef, "HighLatency", ',');
1505     emitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
1506 
1507     bool PostRAScheduler =
1508         (PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false);
1509 
1510     OS << "  " << (PostRAScheduler ? "true" : "false") << ", // "
1511        << "PostRAScheduler\n";
1512 
1513     bool CompleteModel =
1514         (PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false);
1515 
1516     OS << "  " << (CompleteModel ? "true" : "false") << ", // "
1517        << "CompleteModel\n";
1518 
1519     bool EnableIntervals =
1520         (PM.ModelDef ? PM.ModelDef->getValueAsBit("EnableIntervals") : false);
1521 
1522     OS << "  " << (EnableIntervals ? "true" : "false") << ", // "
1523        << "EnableIntervals\n";
1524 
1525     OS << "  " << PM.Index << ", // Processor ID\n";
1526     if (PM.hasInstrSchedModel())
1527       OS << "  " << PM.ModelName << "ProcResources"
1528          << ",\n"
1529          << "  " << PM.ModelName << "SchedClasses"
1530          << ",\n"
1531          << "  " << PM.ProcResourceDefs.size() + 1 << ",\n"
1532          << "  "
1533          << (SchedModels.schedClassEnd() - SchedModels.schedClassBegin())
1534          << ",\n";
1535     else
1536       OS << "  nullptr, nullptr, 0, 0,"
1537          << " // No instruction-level machine model.\n";
1538     if (PM.hasItineraries())
1539       OS << "  " << PM.ItinsDef->getName() << ",\n";
1540     else
1541       OS << "  nullptr, // No Itinerary\n";
1542     if (PM.hasExtraProcessorInfo())
1543       OS << "  &" << PM.ModelName << "ExtraInfo,\n";
1544     else
1545       OS << "  nullptr // No extra processor descriptor\n";
1546     OS << "};\n";
1547   }
1548 }
1549 
1550 //
1551 // EmitSchedModel - Emits all scheduling model tables, folding common patterns.
1552 //
1553 void SubtargetEmitter::emitSchedModel(raw_ostream &OS) {
1554   OS << "#ifdef DBGFIELD\n"
1555      << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
1556      << "#endif\n"
1557      << "#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)\n"
1558      << "#define DBGFIELD(x) x,\n"
1559      << "#else\n"
1560      << "#define DBGFIELD(x)\n"
1561      << "#endif\n";
1562 
1563   if (SchedModels.hasItineraries()) {
1564     std::vector<std::vector<InstrItinerary>> ProcItinLists;
1565     // Emit the stage data
1566     emitStageAndOperandCycleData(OS, ProcItinLists);
1567     emitItineraries(OS, ProcItinLists);
1568   }
1569   OS << "\n// ===============================================================\n"
1570      << "// Data tables for the new per-operand machine model.\n";
1571 
1572   SchedClassTables SchedTables;
1573   for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
1574     genSchedClassTables(ProcModel, SchedTables);
1575   }
1576   emitSchedClassTables(SchedTables, OS);
1577 
1578   OS << "\n#undef DBGFIELD\n";
1579 
1580   // Emit the processor machine model
1581   emitProcessorModels(OS);
1582 }
1583 
1584 static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) {
1585   std::string Buffer;
1586   raw_string_ostream Stream(Buffer);
1587 
1588   // Print all PredicateProlog records to the output stream.
1589   for (const Record *P : Records.getAllDerivedDefinitions("PredicateProlog"))
1590     Stream << P->getValueAsString("Code") << '\n';
1591 
1592   OS << Buffer;
1593 }
1594 
1595 static bool isTruePredicate(const Record *Rec) {
1596   return Rec->isSubClassOf("MCSchedPredicate") &&
1597          Rec->getValueAsDef("Pred")->isSubClassOf("MCTrue");
1598 }
1599 
1600 static void emitPredicates(const CodeGenSchedTransition &T,
1601                            const CodeGenSchedClass &SC, PredicateExpander &PE,
1602                            raw_ostream &OS) {
1603   std::string Buffer;
1604   raw_string_ostream SS(Buffer);
1605 
1606   // If not all predicates are MCTrue, then we need an if-stmt.
1607   unsigned NumNonTruePreds =
1608       T.PredTerm.size() - count_if(T.PredTerm, isTruePredicate);
1609 
1610   SS << PE.getIndent();
1611 
1612   if (NumNonTruePreds) {
1613     bool FirstNonTruePredicate = true;
1614     SS << "if (";
1615 
1616     PE.getIndent() += 2;
1617 
1618     for (const Record *Rec : T.PredTerm) {
1619       // Skip predicates that evaluate to "true".
1620       if (isTruePredicate(Rec))
1621         continue;
1622 
1623       if (FirstNonTruePredicate) {
1624         FirstNonTruePredicate = false;
1625       } else {
1626         SS << "\n";
1627         SS << PE.getIndent();
1628         SS << "&& ";
1629       }
1630 
1631       if (Rec->isSubClassOf("MCSchedPredicate")) {
1632         PE.expandPredicate(SS, Rec->getValueAsDef("Pred"));
1633         continue;
1634       }
1635 
1636       // Expand this legacy predicate and wrap it around braces if there is more
1637       // than one predicate to expand.
1638       SS << ((NumNonTruePreds > 1) ? "(" : "")
1639          << Rec->getValueAsString("Predicate")
1640          << ((NumNonTruePreds > 1) ? ")" : "");
1641     }
1642 
1643     SS << ")\n"; // end of if-stmt
1644     --PE.getIndent();
1645     SS << PE.getIndent();
1646     --PE.getIndent();
1647   }
1648 
1649   SS << "return " << T.ToClassIdx << "; // " << SC.Name << '\n';
1650   OS << Buffer;
1651 }
1652 
1653 // Used by method `SubtargetEmitter::emitSchedModelHelpersImpl()` to generate
1654 // epilogue code for the auto-generated helper.
1655 static void emitSchedModelHelperEpilogue(raw_ostream &OS,
1656                                          bool ShouldReturnZero) {
1657   if (ShouldReturnZero) {
1658     OS << "  // Don't know how to resolve this scheduling class.\n"
1659        << "  return 0;\n";
1660     return;
1661   }
1662 
1663   OS << "  report_fatal_error(\"Expected a variant SchedClass\");\n";
1664 }
1665 
1666 static bool hasMCSchedPredicates(const CodeGenSchedTransition &T) {
1667   return all_of(T.PredTerm, [](const Record *Rec) {
1668     return Rec->isSubClassOf("MCSchedPredicate");
1669   });
1670 }
1671 
1672 static void collectVariantClasses(const CodeGenSchedModels &SchedModels,
1673                                   IdxVec &VariantClasses,
1674                                   bool OnlyExpandMCInstPredicates) {
1675   for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
1676     // Ignore non-variant scheduling classes.
1677     if (SC.Transitions.empty())
1678       continue;
1679 
1680     if (OnlyExpandMCInstPredicates) {
1681       // Ignore this variant scheduling class no transitions use any meaningful
1682       // MCSchedPredicate definitions.
1683       if (llvm::none_of(SC.Transitions, hasMCSchedPredicates))
1684         continue;
1685     }
1686 
1687     VariantClasses.push_back(SC.Index);
1688   }
1689 }
1690 
1691 static void collectProcessorIndices(const CodeGenSchedClass &SC,
1692                                     IdxVec &ProcIndices) {
1693   // A variant scheduling class may define transitions for multiple
1694   // processors.  This function identifies wich processors are associated with
1695   // transition rules specified by variant class `SC`.
1696   for (const CodeGenSchedTransition &T : SC.Transitions) {
1697     IdxVec PI;
1698     std::set_union(&T.ProcIndex, &T.ProcIndex + 1, ProcIndices.begin(),
1699                    ProcIndices.end(), std::back_inserter(PI));
1700     ProcIndices = std::move(PI);
1701   }
1702 }
1703 
1704 static bool isAlwaysTrue(const CodeGenSchedTransition &T) {
1705   return llvm::all_of(T.PredTerm, isTruePredicate);
1706 }
1707 
1708 void SubtargetEmitter::emitSchedModelHelpersImpl(
1709     raw_ostream &OS, bool OnlyExpandMCInstPredicates) {
1710   IdxVec VariantClasses;
1711   collectVariantClasses(SchedModels, VariantClasses,
1712                         OnlyExpandMCInstPredicates);
1713 
1714   if (VariantClasses.empty()) {
1715     emitSchedModelHelperEpilogue(OS, OnlyExpandMCInstPredicates);
1716     return;
1717   }
1718 
1719   // Construct a switch statement where the condition is a check on the
1720   // scheduling class identifier. There is a `case` for every variant class
1721   // defined by the processor models of this target.
1722   // Each `case` implements a number of rules to resolve (i.e. to transition
1723   // from) a variant scheduling class to another scheduling class.  Rules are
1724   // described by instances of CodeGenSchedTransition. Note that transitions may
1725   // not be valid for all processors.
1726   OS << "  switch (SchedClass) {\n";
1727   for (unsigned VC : VariantClasses) {
1728     IdxVec ProcIndices;
1729     const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
1730     collectProcessorIndices(SC, ProcIndices);
1731 
1732     OS << "  case " << VC << ": // " << SC.Name << '\n';
1733 
1734     PredicateExpander PE(Target);
1735     PE.setByRef(false);
1736     PE.setExpandForMC(OnlyExpandMCInstPredicates);
1737     for (unsigned PI : ProcIndices) {
1738       OS << "    ";
1739 
1740       // Emit a guard on the processor ID.
1741       if (PI != 0) {
1742         OS << (OnlyExpandMCInstPredicates
1743                    ? "if (CPUID == "
1744                    : "if (SchedModel->getProcessorID() == ");
1745         OS << PI << ") ";
1746         OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName << '\n';
1747       }
1748 
1749       // Now emit transitions associated with processor PI.
1750       const CodeGenSchedTransition *FinalT = nullptr;
1751       for (const CodeGenSchedTransition &T : SC.Transitions) {
1752         if (PI != 0 && T.ProcIndex != PI)
1753           continue;
1754 
1755         // Emit only transitions based on MCSchedPredicate, if it's the case.
1756         // At least the transition specified by NoSchedPred is emitted,
1757         // which becomes the default transition for those variants otherwise
1758         // not based on MCSchedPredicate.
1759         // FIXME: preferably, llvm-mca should instead assume a reasonable
1760         // default when a variant transition is not based on MCSchedPredicate
1761         // for a given processor.
1762         if (OnlyExpandMCInstPredicates && !hasMCSchedPredicates(T))
1763           continue;
1764 
1765         // If transition is folded to 'return X' it should be the last one.
1766         if (isAlwaysTrue(T)) {
1767           FinalT = &T;
1768           continue;
1769         }
1770         PE.getIndent() = 3;
1771         emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PE, OS);
1772       }
1773       if (FinalT)
1774         emitPredicates(*FinalT, SchedModels.getSchedClass(FinalT->ToClassIdx),
1775                        PE, OS);
1776 
1777       OS << "    }\n";
1778 
1779       if (PI == 0)
1780         break;
1781     }
1782 
1783     if (SC.isInferred())
1784       OS << "    return " << SC.Index << ";\n";
1785     OS << "    break;\n";
1786   }
1787 
1788   OS << "  };\n";
1789 
1790   emitSchedModelHelperEpilogue(OS, OnlyExpandMCInstPredicates);
1791 }
1792 
1793 void SubtargetEmitter::emitSchedModelHelpers(const std::string &ClassName,
1794                                              raw_ostream &OS) {
1795   OS << "unsigned " << ClassName
1796      << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
1797      << " const TargetSchedModel *SchedModel) const {\n";
1798 
1799   // Emit the predicate prolog code.
1800   emitPredicateProlog(Records, OS);
1801 
1802   // Emit target predicates.
1803   emitSchedModelHelpersImpl(OS);
1804 
1805   OS << "} // " << ClassName << "::resolveSchedClass\n\n";
1806 
1807   OS << "unsigned " << ClassName
1808      << "\n::resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI,"
1809      << " const MCInstrInfo *MCII, unsigned CPUID) const {\n"
1810      << "  return " << Target << "_MC"
1811      << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, CPUID);\n"
1812      << "} // " << ClassName << "::resolveVariantSchedClass\n\n";
1813 
1814   STIPredicateExpander PE(Target, /*Indent=*/0);
1815   PE.setClassPrefix(ClassName);
1816   PE.setExpandDefinition(true);
1817   PE.setByRef(false);
1818 
1819   for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
1820     PE.expandSTIPredicate(OS, Fn);
1821 }
1822 
1823 void SubtargetEmitter::emitHwModeCheck(const std::string &ClassName,
1824                                        raw_ostream &OS) {
1825   const CodeGenHwModes &CGH = TGT.getHwModes();
1826   assert(CGH.getNumModeIds() > 0);
1827   if (CGH.getNumModeIds() == 1)
1828     return;
1829 
1830   // Collect all HwModes and related features defined in the TD files,
1831   // and store them as a bit set.
1832   unsigned ValueTypeModes = 0;
1833   unsigned RegInfoModes = 0;
1834   unsigned EncodingInfoModes = 0;
1835   for (const auto &MS : CGH.getHwModeSelects()) {
1836     for (const HwModeSelect::PairType &P : MS.second.Items) {
1837       if (P.first == DefaultMode)
1838         continue;
1839       if (P.second->isSubClassOf("ValueType")) {
1840         ValueTypeModes |= (1 << (P.first - 1));
1841       } else if (P.second->isSubClassOf("RegInfo") ||
1842                  P.second->isSubClassOf("SubRegRange")) {
1843         RegInfoModes |= (1 << (P.first - 1));
1844       } else if (P.second->isSubClassOf("InstructionEncoding")) {
1845         EncodingInfoModes |= (1 << (P.first - 1));
1846       }
1847     }
1848   }
1849 
1850   // Start emitting for getHwModeSet().
1851   OS << "unsigned " << ClassName << "::getHwModeSet() const {\n";
1852   OS << "  // Collect HwModes and store them as a bit set.\n";
1853   OS << "  unsigned Modes = 0;\n";
1854   for (unsigned M = 1, NumModes = CGH.getNumModeIds(); M != NumModes; ++M) {
1855     const HwMode &HM = CGH.getMode(M);
1856     OS << "  if (checkFeatures(\"" << HM.Features << "\")) Modes |= (1 << "
1857        << (M - 1) << ");\n";
1858   }
1859   OS << "  return Modes;\n}\n";
1860   // End emitting for getHwModeSet().
1861 
1862   auto HandlePerMode = [&](std::string ModeType, unsigned ModeInBitSet) {
1863     OS << "  case HwMode_" << ModeType << ":\n"
1864        << "    Modes &= " << ModeInBitSet << ";\n"
1865        << "    if (!Modes)\n      return Modes;\n"
1866        << "    if (!llvm::has_single_bit<unsigned>(Modes))\n"
1867        << "      llvm_unreachable(\"Two or more HwModes for " << ModeType
1868        << " were found!\");\n"
1869        << "    return llvm::countr_zero(Modes) + 1;\n";
1870   };
1871 
1872   // Start emitting for getHwMode().
1873   OS << "unsigned " << ClassName
1874      << "::getHwMode(enum HwModeType type) const {\n";
1875   OS << "  unsigned Modes = getHwModeSet();\n\n";
1876   OS << "  if (!Modes)\n    return Modes;\n\n";
1877   OS << "  switch (type) {\n";
1878   OS << "  case HwMode_Default:\n    return llvm::countr_zero(Modes) + 1;\n";
1879   HandlePerMode("ValueType", ValueTypeModes);
1880   HandlePerMode("RegInfo", RegInfoModes);
1881   HandlePerMode("EncodingInfo", EncodingInfoModes);
1882   OS << "  }\n";
1883   OS << "  llvm_unreachable(\"unexpected HwModeType\");\n"
1884      << "  return 0; // should not get here\n}\n";
1885   // End emitting for getHwMode().
1886 }
1887 
1888 void SubtargetEmitter::emitGetMacroFusions(const std::string &ClassName,
1889                                            raw_ostream &OS) {
1890   if (!TGT.hasMacroFusion())
1891     return;
1892 
1893   OS << "std::vector<MacroFusionPredTy> " << ClassName
1894      << "::getMacroFusions() const {\n";
1895   OS.indent(2) << "std::vector<MacroFusionPredTy> Fusions;\n";
1896   for (auto *Fusion : TGT.getMacroFusions()) {
1897     std::string Name = Fusion->getNameInitAsString();
1898     OS.indent(2) << "if (hasFeature(" << Target << "::" << Name
1899                  << ")) Fusions.push_back(llvm::is" << Name << ");\n";
1900   }
1901 
1902   OS.indent(2) << "return Fusions;\n";
1903   OS << "}\n";
1904 }
1905 
1906 // Produces a subtarget specific function for parsing
1907 // the subtarget features string.
1908 void SubtargetEmitter::parseFeaturesFunction(raw_ostream &OS) {
1909   ArrayRef<const Record *> Features =
1910       Records.getAllDerivedDefinitions("SubtargetFeature");
1911 
1912   OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1913      << "// subtarget options.\n"
1914      << "void llvm::";
1915   OS << Target;
1916   OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, "
1917      << "StringRef FS) {\n"
1918      << "  LLVM_DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
1919      << "  LLVM_DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"
1920      << "  LLVM_DEBUG(dbgs() << \"\\nTuneCPU:\" << TuneCPU << \"\\n\\n\");\n";
1921 
1922   if (Features.empty()) {
1923     OS << "}\n";
1924     return;
1925   }
1926 
1927   if (Target == "AArch64")
1928     OS << "  CPU = AArch64::resolveCPUAlias(CPU);\n"
1929        << "  TuneCPU = AArch64::resolveCPUAlias(TuneCPU);\n";
1930 
1931   OS << "  InitMCProcessorInfo(CPU, TuneCPU, FS);\n"
1932      << "  const FeatureBitset &Bits = getFeatureBits();\n";
1933 
1934   for (const Record *R : Features) {
1935     // Next record
1936     StringRef Instance = R->getName();
1937     StringRef Value = R->getValueAsString("Value");
1938     StringRef FieldName = R->getValueAsString("FieldName");
1939 
1940     if (Value == "true" || Value == "false")
1941       OS << "  if (Bits[" << Target << "::" << Instance << "]) " << FieldName
1942          << " = " << Value << ";\n";
1943     else
1944       OS << "  if (Bits[" << Target << "::" << Instance << "] && " << FieldName
1945          << " < " << Value << ") " << FieldName << " = " << Value << ";\n";
1946   }
1947 
1948   OS << "}\n";
1949 }
1950 
1951 void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
1952   OS << "namespace " << Target << "_MC {\n"
1953      << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n"
1954      << "    const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID) {\n";
1955   emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true);
1956   OS << "}\n";
1957   OS << "} // end namespace " << Target << "_MC\n\n";
1958 
1959   OS << "struct " << Target
1960      << "GenMCSubtargetInfo : public MCSubtargetInfo {\n";
1961   OS << "  " << Target << "GenMCSubtargetInfo(const Triple &TT,\n"
1962      << "    StringRef CPU, StringRef TuneCPU, StringRef FS,\n"
1963      << "    ArrayRef<StringRef> PN,\n"
1964      << "    ArrayRef<SubtargetFeatureKV> PF,\n"
1965      << "    ArrayRef<SubtargetSubTypeKV> PD,\n"
1966      << "    const MCWriteProcResEntry *WPR,\n"
1967      << "    const MCWriteLatencyEntry *WL,\n"
1968      << "    const MCReadAdvanceEntry *RA, const InstrStage *IS,\n"
1969      << "    const unsigned *OC, const unsigned *FP) :\n"
1970      << "      MCSubtargetInfo(TT, CPU, TuneCPU, FS, PN, PF, PD,\n"
1971      << "                      WPR, WL, RA, IS, OC, FP) { }\n\n"
1972      << "  unsigned resolveVariantSchedClass(unsigned SchedClass,\n"
1973      << "      const MCInst *MI, const MCInstrInfo *MCII,\n"
1974      << "      unsigned CPUID) const override {\n"
1975      << "    return " << Target << "_MC"
1976      << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, CPUID);\n";
1977   OS << "  }\n";
1978   if (TGT.getHwModes().getNumModeIds() > 1) {
1979     OS << "  unsigned getHwModeSet() const override;\n";
1980     OS << "  unsigned getHwMode(enum HwModeType type = HwMode_Default) const "
1981           "override;\n";
1982   }
1983   if (Target == "AArch64")
1984     OS << "  bool isCPUStringValid(StringRef CPU) const override {\n"
1985        << "    CPU = AArch64::resolveCPUAlias(CPU);\n"
1986        << "    return MCSubtargetInfo::isCPUStringValid(CPU);\n"
1987        << "  }\n";
1988   OS << "};\n";
1989   emitHwModeCheck(Target + "GenMCSubtargetInfo", OS);
1990 }
1991 
1992 void SubtargetEmitter::emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS) {
1993   OS << "\n#ifdef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n";
1994   OS << "#undef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n";
1995 
1996   STIPredicateExpander PE(Target, /*Indent=*/0);
1997   PE.setExpandForMC(true);
1998   PE.setByRef(true);
1999   for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
2000     PE.expandSTIPredicate(OS, Fn);
2001 
2002   OS << "#endif // GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n";
2003 
2004   OS << "\n#ifdef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n";
2005   OS << "#undef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n";
2006 
2007   std::string ClassPrefix = Target + "MCInstrAnalysis";
2008   PE.setExpandDefinition(true);
2009   PE.setClassPrefix(ClassPrefix);
2010   for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
2011     PE.expandSTIPredicate(OS, Fn);
2012 
2013   OS << "#endif // GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n";
2014 }
2015 
2016 //
2017 // SubtargetEmitter::run - Main subtarget enumeration emitter.
2018 //
2019 void SubtargetEmitter::run(raw_ostream &OS) {
2020   emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
2021 
2022   OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
2023   OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
2024 
2025   OS << "namespace llvm {\n";
2026   auto FeatureMap = enumeration(OS);
2027   OS << "} // end namespace llvm\n\n";
2028   OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
2029 
2030   emitSubtargetInfoMacroCalls(OS);
2031 
2032   OS << "namespace llvm {\n";
2033   unsigned NumFeatures = featureKeyValues(OS, FeatureMap);
2034   OS << "\n";
2035   emitSchedModel(OS);
2036   OS << "\n";
2037   unsigned NumProcs = cpuKeyValues(OS, FeatureMap);
2038   OS << "\n";
2039   unsigned NumNames = cpuNames(OS);
2040   OS << "\n";
2041 
2042   // MCInstrInfo initialization routine.
2043   emitGenMCSubtargetInfo(OS);
2044 
2045   OS << "\nstatic inline MCSubtargetInfo *create" << Target
2046      << "MCSubtargetInfoImpl("
2047      << "const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS) {\n";
2048   if (Target == "AArch64")
2049     OS << "  CPU = AArch64::resolveCPUAlias(CPU);\n"
2050        << "  TuneCPU = AArch64::resolveCPUAlias(TuneCPU);\n";
2051   OS << "  return new " << Target
2052      << "GenMCSubtargetInfo(TT, CPU, TuneCPU, FS, ";
2053   if (NumNames)
2054     OS << Target << "Names, ";
2055   else
2056     OS << "{}, ";
2057   if (NumFeatures)
2058     OS << Target << "FeatureKV, ";
2059   else
2060     OS << "{}, ";
2061   if (NumProcs)
2062     OS << Target << "SubTypeKV, ";
2063   else
2064     OS << "{}, ";
2065   OS << '\n';
2066   OS.indent(22);
2067   OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, "
2068      << Target << "ReadAdvanceTable, ";
2069   OS << '\n';
2070   OS.indent(22);
2071   if (SchedModels.hasItineraries()) {
2072     OS << Target << "Stages, " << Target << "OperandCycles, " << Target
2073        << "ForwardingPaths";
2074   } else
2075     OS << "nullptr, nullptr, nullptr";
2076   OS << ");\n}\n\n";
2077 
2078   OS << "} // end namespace llvm\n\n";
2079 
2080   OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
2081 
2082   OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
2083   OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n";
2084 
2085   OS << "#include \"llvm/Support/Debug.h\"\n";
2086   OS << "#include \"llvm/Support/raw_ostream.h\"\n\n";
2087   if (Target == "AArch64")
2088     OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n";
2089   parseFeaturesFunction(OS);
2090 
2091   OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
2092 
2093   // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
2094   OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
2095   OS << "#undef GET_SUBTARGETINFO_HEADER\n\n";
2096 
2097   std::string ClassName = Target + "GenSubtargetInfo";
2098   OS << "namespace llvm {\n";
2099   OS << "class DFAPacketizer;\n";
2100   OS << "namespace " << Target << "_MC {\n"
2101      << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,"
2102      << " const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID);\n"
2103      << "} // end namespace " << Target << "_MC\n\n";
2104   OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
2105      << "  explicit " << ClassName << "(const Triple &TT, StringRef CPU, "
2106      << "StringRef TuneCPU, StringRef FS);\n"
2107      << "public:\n"
2108      << "  unsigned resolveSchedClass(unsigned SchedClass, "
2109      << " const MachineInstr *DefMI,"
2110      << " const TargetSchedModel *SchedModel) const override;\n"
2111      << "  unsigned resolveVariantSchedClass(unsigned SchedClass,"
2112      << " const MCInst *MI, const MCInstrInfo *MCII,"
2113      << " unsigned CPUID) const override;\n"
2114      << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
2115      << " const;\n";
2116   if (TGT.getHwModes().getNumModeIds() > 1) {
2117     OS << "  unsigned getHwModeSet() const override;\n";
2118     OS << "  unsigned getHwMode(enum HwModeType type = HwMode_Default) const "
2119           "override;\n";
2120   }
2121   if (TGT.hasMacroFusion())
2122     OS << "  std::vector<MacroFusionPredTy> getMacroFusions() const "
2123           "override;\n";
2124 
2125   STIPredicateExpander PE(Target);
2126   PE.setByRef(false);
2127   for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
2128     PE.expandSTIPredicate(OS, Fn);
2129 
2130   OS << "};\n"
2131      << "} // end namespace llvm\n\n";
2132 
2133   OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
2134 
2135   OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
2136   OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
2137 
2138   OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
2139   OS << "namespace llvm {\n";
2140   OS << "extern const llvm::StringRef " << Target << "Names[];\n";
2141   OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
2142   OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n";
2143   OS << "extern const llvm::MCWriteProcResEntry " << Target
2144      << "WriteProcResTable[];\n";
2145   OS << "extern const llvm::MCWriteLatencyEntry " << Target
2146      << "WriteLatencyTable[];\n";
2147   OS << "extern const llvm::MCReadAdvanceEntry " << Target
2148      << "ReadAdvanceTable[];\n";
2149 
2150   if (SchedModels.hasItineraries()) {
2151     OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
2152     OS << "extern const unsigned " << Target << "OperandCycles[];\n";
2153     OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
2154   }
2155 
2156   OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, "
2157      << "StringRef TuneCPU, StringRef FS)\n";
2158 
2159   if (Target == "AArch64")
2160     OS << "  : TargetSubtargetInfo(TT, AArch64::resolveCPUAlias(CPU),\n"
2161        << "                        AArch64::resolveCPUAlias(TuneCPU), FS, ";
2162   else
2163     OS << "  : TargetSubtargetInfo(TT, CPU, TuneCPU, FS, ";
2164   if (NumNames)
2165     OS << "ArrayRef(" << Target << "Names, " << NumNames << "), ";
2166   else
2167     OS << "{}, ";
2168   if (NumFeatures)
2169     OS << "ArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), ";
2170   else
2171     OS << "{}, ";
2172   if (NumProcs)
2173     OS << "ArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
2174   else
2175     OS << "{}, ";
2176   OS << '\n';
2177   OS.indent(24);
2178   OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, "
2179      << Target << "ReadAdvanceTable, ";
2180   OS << '\n';
2181   OS.indent(24);
2182   if (SchedModels.hasItineraries()) {
2183     OS << Target << "Stages, " << Target << "OperandCycles, " << Target
2184        << "ForwardingPaths";
2185   } else
2186     OS << "nullptr, nullptr, nullptr";
2187   OS << ") {}\n\n";
2188 
2189   emitSchedModelHelpers(ClassName, OS);
2190   emitHwModeCheck(ClassName, OS);
2191   emitGetMacroFusions(ClassName, OS);
2192 
2193   OS << "} // end namespace llvm\n\n";
2194 
2195   OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
2196 
2197   emitMcInstrAnalysisPredicateFunctions(OS);
2198 }
2199 
2200 static TableGen::Emitter::OptClass<SubtargetEmitter>
2201     X("gen-subtarget", "Generate subtarget enumerations");
2202