1//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tablegen backend emits subtarget enumerations.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "subtarget-emitter"
15
16#include "CodeGenTarget.h"
17#include "CodeGenSchedule.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/MC/MCInstrItineraries.h"
21#include "llvm/TableGen/Error.h"
22#include "llvm/TableGen/Record.h"
23#include "llvm/TableGen/TableGenBackend.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/Format.h"
26#include <algorithm>
27#include <map>
28#include <string>
29#include <vector>
30using namespace llvm;
31
32namespace {
33class SubtargetEmitter {
34  // Each processor has a SchedClassDesc table with an entry for each SchedClass.
35  // The SchedClassDesc table indexes into a global write resource table, write
36  // latency table, and read advance table.
37  struct SchedClassTables {
38    std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
39    std::vector<MCWriteProcResEntry> WriteProcResources;
40    std::vector<MCWriteLatencyEntry> WriteLatencies;
41    std::vector<std::string> WriterNames;
42    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
43
44    // Reserve an invalid entry at index 0
45    SchedClassTables() {
46      ProcSchedClasses.resize(1);
47      WriteProcResources.resize(1);
48      WriteLatencies.resize(1);
49      WriterNames.push_back("InvalidWrite");
50      ReadAdvanceEntries.resize(1);
51    }
52  };
53
54  struct LessWriteProcResources {
55    bool operator()(const MCWriteProcResEntry &LHS,
56                    const MCWriteProcResEntry &RHS) {
57      return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
58    }
59  };
60
61  RecordKeeper &Records;
62  CodeGenSchedModels &SchedModels;
63  std::string Target;
64
65  void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
66  unsigned FeatureKeyValues(raw_ostream &OS);
67  unsigned CPUKeyValues(raw_ostream &OS);
68  void FormItineraryStageString(const std::string &Names,
69                                Record *ItinData, std::string &ItinString,
70                                unsigned &NStages);
71  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
72                                       unsigned &NOperandCycles);
73  void FormItineraryBypassString(const std::string &Names,
74                                 Record *ItinData,
75                                 std::string &ItinString, unsigned NOperandCycles);
76  void EmitStageAndOperandCycleData(raw_ostream &OS,
77                                    std::vector<std::vector<InstrItinerary> >
78                                      &ProcItinLists);
79  void EmitItineraries(raw_ostream &OS,
80                       std::vector<std::vector<InstrItinerary> >
81                         &ProcItinLists);
82  void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
83                         char Separator);
84  void EmitProcessorResources(const CodeGenProcModel &ProcModel,
85                              raw_ostream &OS);
86  Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
87                             const CodeGenProcModel &ProcModel);
88  Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
89                          const CodeGenProcModel &ProcModel);
90  void GenSchedClassTables(const CodeGenProcModel &ProcModel,
91                           SchedClassTables &SchedTables);
92  void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
93  void EmitProcessorModels(raw_ostream &OS);
94  void EmitProcessorLookup(raw_ostream &OS);
95  void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS);
96  void EmitSchedModel(raw_ostream &OS);
97  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
98                             unsigned NumProcs);
99
100public:
101  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
102    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
103
104  void run(raw_ostream &o);
105
106};
107} // End anonymous namespace
108
109//
110// Enumeration - Emit the specified class as an enumeration.
111//
112void SubtargetEmitter::Enumeration(raw_ostream &OS,
113                                   const char *ClassName,
114                                   bool isBits) {
115  // Get all records of class and sort
116  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
117  std::sort(DefList.begin(), DefList.end(), LessRecord());
118
119  unsigned N = DefList.size();
120  if (N == 0)
121    return;
122  if (N > 64) {
123    errs() << "Too many (> 64) subtarget features!\n";
124    exit(1);
125  }
126
127  OS << "namespace " << Target << " {\n";
128
129  // For bit flag enumerations with more than 32 items, emit constants.
130  // Emit an enum for everything else.
131  if (isBits && N > 32) {
132    // For each record
133    for (unsigned i = 0; i < N; i++) {
134      // Next record
135      Record *Def = DefList[i];
136
137      // Get and emit name and expression (1 << i)
138      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
139    }
140  } else {
141    // Open enumeration
142    OS << "enum {\n";
143
144    // For each record
145    for (unsigned i = 0; i < N;) {
146      // Next record
147      Record *Def = DefList[i];
148
149      // Get and emit name
150      OS << "  " << Def->getName();
151
152      // If bit flags then emit expression (1 << i)
153      if (isBits)  OS << " = " << " 1ULL << " << i;
154
155      // Depending on 'if more in the list' emit comma
156      if (++i < N) OS << ",";
157
158      OS << "\n";
159    }
160
161    // Close enumeration
162    OS << "};\n";
163  }
164
165  OS << "}\n";
166}
167
168//
169// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
170// command line.
171//
172unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
173  // Gather and sort all the features
174  std::vector<Record*> FeatureList =
175                           Records.getAllDerivedDefinitions("SubtargetFeature");
176
177  if (FeatureList.empty())
178    return 0;
179
180  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
181
182  // Begin feature table
183  OS << "// Sorted (by key) array of values for CPU features.\n"
184     << "extern const llvm::SubtargetFeatureKV " << Target
185     << "FeatureKV[] = {\n";
186
187  // For each feature
188  unsigned NumFeatures = 0;
189  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
190    // Next feature
191    Record *Feature = FeatureList[i];
192
193    const std::string &Name = Feature->getName();
194    const std::string &CommandLineName = Feature->getValueAsString("Name");
195    const std::string &Desc = Feature->getValueAsString("Desc");
196
197    if (CommandLineName.empty()) continue;
198
199    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
200    OS << "  { "
201       << "\"" << CommandLineName << "\", "
202       << "\"" << Desc << "\", "
203       << Target << "::" << Name << ", ";
204
205    const std::vector<Record*> &ImpliesList =
206      Feature->getValueAsListOfDefs("Implies");
207
208    if (ImpliesList.empty()) {
209      OS << "0ULL";
210    } else {
211      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
212        OS << Target << "::" << ImpliesList[j]->getName();
213        if (++j < M) OS << " | ";
214      }
215    }
216
217    OS << " }";
218    ++NumFeatures;
219
220    // Depending on 'if more in the list' emit comma
221    if ((i + 1) < N) OS << ",";
222
223    OS << "\n";
224  }
225
226  // End feature table
227  OS << "};\n";
228
229  return NumFeatures;
230}
231
232//
233// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
234// line.
235//
236unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
237  // Gather and sort processor information
238  std::vector<Record*> ProcessorList =
239                          Records.getAllDerivedDefinitions("Processor");
240  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
241
242  // Begin processor table
243  OS << "// Sorted (by key) array of values for CPU subtype.\n"
244     << "extern const llvm::SubtargetFeatureKV " << Target
245     << "SubTypeKV[] = {\n";
246
247  // For each processor
248  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
249    // Next processor
250    Record *Processor = ProcessorList[i];
251
252    const std::string &Name = Processor->getValueAsString("Name");
253    const std::vector<Record*> &FeatureList =
254      Processor->getValueAsListOfDefs("Features");
255
256    // Emit as { "cpu", "description", f1 | f2 | ... fn },
257    OS << "  { "
258       << "\"" << Name << "\", "
259       << "\"Select the " << Name << " processor\", ";
260
261    if (FeatureList.empty()) {
262      OS << "0ULL";
263    } else {
264      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
265        OS << Target << "::" << FeatureList[j]->getName();
266        if (++j < M) OS << " | ";
267      }
268    }
269
270    // The "0" is for the "implies" section of this data structure.
271    OS << ", 0ULL }";
272
273    // Depending on 'if more in the list' emit comma
274    if (++i < N) OS << ",";
275
276    OS << "\n";
277  }
278
279  // End processor table
280  OS << "};\n";
281
282  return ProcessorList.size();
283}
284
285//
286// FormItineraryStageString - Compose a string containing the stage
287// data initialization for the specified itinerary.  N is the number
288// of stages.
289//
290void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
291                                                Record *ItinData,
292                                                std::string &ItinString,
293                                                unsigned &NStages) {
294  // Get states list
295  const std::vector<Record*> &StageList =
296    ItinData->getValueAsListOfDefs("Stages");
297
298  // For each stage
299  unsigned N = NStages = StageList.size();
300  for (unsigned i = 0; i < N;) {
301    // Next stage
302    const Record *Stage = StageList[i];
303
304    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
305    int Cycles = Stage->getValueAsInt("Cycles");
306    ItinString += "  { " + itostr(Cycles) + ", ";
307
308    // Get unit list
309    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
310
311    // For each unit
312    for (unsigned j = 0, M = UnitList.size(); j < M;) {
313      // Add name and bitwise or
314      ItinString += Name + "FU::" + UnitList[j]->getName();
315      if (++j < M) ItinString += " | ";
316    }
317
318    int TimeInc = Stage->getValueAsInt("TimeInc");
319    ItinString += ", " + itostr(TimeInc);
320
321    int Kind = Stage->getValueAsInt("Kind");
322    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
323
324    // Close off stage
325    ItinString += " }";
326    if (++i < N) ItinString += ", ";
327  }
328}
329
330//
331// FormItineraryOperandCycleString - Compose a string containing the
332// operand cycle initialization for the specified itinerary.  N is the
333// number of operands that has cycles specified.
334//
335void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
336                         std::string &ItinString, unsigned &NOperandCycles) {
337  // Get operand cycle list
338  const std::vector<int64_t> &OperandCycleList =
339    ItinData->getValueAsListOfInts("OperandCycles");
340
341  // For each operand cycle
342  unsigned N = NOperandCycles = OperandCycleList.size();
343  for (unsigned i = 0; i < N;) {
344    // Next operand cycle
345    const int OCycle = OperandCycleList[i];
346
347    ItinString += "  " + itostr(OCycle);
348    if (++i < N) ItinString += ", ";
349  }
350}
351
352void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
353                                                 Record *ItinData,
354                                                 std::string &ItinString,
355                                                 unsigned NOperandCycles) {
356  const std::vector<Record*> &BypassList =
357    ItinData->getValueAsListOfDefs("Bypasses");
358  unsigned N = BypassList.size();
359  unsigned i = 0;
360  for (; i < N;) {
361    ItinString += Name + "Bypass::" + BypassList[i]->getName();
362    if (++i < NOperandCycles) ItinString += ", ";
363  }
364  for (; i < NOperandCycles;) {
365    ItinString += " 0";
366    if (++i < NOperandCycles) ItinString += ", ";
367  }
368}
369
370//
371// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
372// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
373// by CodeGenSchedClass::Index.
374//
375void SubtargetEmitter::
376EmitStageAndOperandCycleData(raw_ostream &OS,
377                             std::vector<std::vector<InstrItinerary> >
378                               &ProcItinLists) {
379
380  // Multiple processor models may share an itinerary record. Emit it once.
381  SmallPtrSet<Record*, 8> ItinsDefSet;
382
383  // Emit functional units for all the itineraries.
384  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
385         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
386
387    if (!ItinsDefSet.insert(PI->ItinsDef))
388      continue;
389
390    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
391    if (FUs.empty())
392      continue;
393
394    const std::string &Name = PI->ItinsDef->getName();
395    OS << "\n// Functional units for \"" << Name << "\"\n"
396       << "namespace " << Name << "FU {\n";
397
398    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
399      OS << "  const unsigned " << FUs[j]->getName()
400         << " = 1 << " << j << ";\n";
401
402    OS << "}\n";
403
404    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
405    if (BPs.size()) {
406      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
407         << "\"\n" << "namespace " << Name << "Bypass {\n";
408
409      OS << "  const unsigned NoBypass = 0;\n";
410      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
411        OS << "  const unsigned " << BPs[j]->getName()
412           << " = 1 << " << j << ";\n";
413
414      OS << "}\n";
415    }
416  }
417
418  // Begin stages table
419  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
420                           "Stages[] = {\n";
421  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
422
423  // Begin operand cycle table
424  std::string OperandCycleTable = "extern const unsigned " + Target +
425    "OperandCycles[] = {\n";
426  OperandCycleTable += "  0, // No itinerary\n";
427
428  // Begin pipeline bypass table
429  std::string BypassTable = "extern const unsigned " + Target +
430    "ForwardingPaths[] = {\n";
431  BypassTable += " 0, // No itinerary\n";
432
433  // For each Itinerary across all processors, add a unique entry to the stages,
434  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
435  // object with computed offsets to the ProcItinLists result.
436  unsigned StageCount = 1, OperandCycleCount = 1;
437  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
438  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
439         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
440    const CodeGenProcModel &ProcModel = *PI;
441
442    // Add process itinerary to the list.
443    ProcItinLists.resize(ProcItinLists.size()+1);
444
445    // If this processor defines no itineraries, then leave the itinerary list
446    // empty.
447    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
448    if (ProcModel.ItinDefList.empty())
449      continue;
450
451    // Reserve index==0 for NoItinerary.
452    ItinList.resize(SchedModels.numItineraryClasses()+1);
453
454    const std::string &Name = ProcModel.ItinsDef->getName();
455
456    // For each itinerary data
457    for (unsigned SchedClassIdx = 0,
458           SchedClassEnd = ProcModel.ItinDefList.size();
459         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
460
461      // Next itinerary data
462      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
463
464      // Get string and stage count
465      std::string ItinStageString;
466      unsigned NStages = 0;
467      if (ItinData)
468        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
469
470      // Get string and operand cycle count
471      std::string ItinOperandCycleString;
472      unsigned NOperandCycles = 0;
473      std::string ItinBypassString;
474      if (ItinData) {
475        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
476                                        NOperandCycles);
477
478        FormItineraryBypassString(Name, ItinData, ItinBypassString,
479                                  NOperandCycles);
480      }
481
482      // Check to see if stage already exists and create if it doesn't
483      unsigned FindStage = 0;
484      if (NStages > 0) {
485        FindStage = ItinStageMap[ItinStageString];
486        if (FindStage == 0) {
487          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
488          StageTable += ItinStageString + ", // " + itostr(StageCount);
489          if (NStages > 1)
490            StageTable += "-" + itostr(StageCount + NStages - 1);
491          StageTable += "\n";
492          // Record Itin class number.
493          ItinStageMap[ItinStageString] = FindStage = StageCount;
494          StageCount += NStages;
495        }
496      }
497
498      // Check to see if operand cycle already exists and create if it doesn't
499      unsigned FindOperandCycle = 0;
500      if (NOperandCycles > 0) {
501        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
502        FindOperandCycle = ItinOperandMap[ItinOperandString];
503        if (FindOperandCycle == 0) {
504          // Emit as  cycle, // index
505          OperandCycleTable += ItinOperandCycleString + ", // ";
506          std::string OperandIdxComment = itostr(OperandCycleCount);
507          if (NOperandCycles > 1)
508            OperandIdxComment += "-"
509              + itostr(OperandCycleCount + NOperandCycles - 1);
510          OperandCycleTable += OperandIdxComment + "\n";
511          // Record Itin class number.
512          ItinOperandMap[ItinOperandCycleString] =
513            FindOperandCycle = OperandCycleCount;
514          // Emit as bypass, // index
515          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
516          OperandCycleCount += NOperandCycles;
517        }
518      }
519
520      // Set up itinerary as location and location + stage count
521      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
522      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
523                                    FindOperandCycle,
524                                    FindOperandCycle + NOperandCycles};
525
526      // Inject - empty slots will be 0, 0
527      ItinList[SchedClassIdx] = Intinerary;
528    }
529  }
530
531  // Closing stage
532  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
533  StageTable += "};\n";
534
535  // Closing operand cycles
536  OperandCycleTable += "  0 // End operand cycles\n";
537  OperandCycleTable += "};\n";
538
539  BypassTable += " 0 // End bypass tables\n";
540  BypassTable += "};\n";
541
542  // Emit tables.
543  OS << StageTable;
544  OS << OperandCycleTable;
545  OS << BypassTable;
546}
547
548//
549// EmitProcessorData - Generate data for processor itineraries that were
550// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
551// Itineraries for each processor. The Itinerary lists are indexed on
552// CodeGenSchedClass::Index.
553//
554void SubtargetEmitter::
555EmitItineraries(raw_ostream &OS,
556                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
557
558  // Multiple processor models may share an itinerary record. Emit it once.
559  SmallPtrSet<Record*, 8> ItinsDefSet;
560
561  // For each processor's machine model
562  std::vector<std::vector<InstrItinerary> >::iterator
563      ProcItinListsIter = ProcItinLists.begin();
564  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
565         PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
566
567    Record *ItinsDef = PI->ItinsDef;
568    if (!ItinsDefSet.insert(ItinsDef))
569      continue;
570
571    // Get processor itinerary name
572    const std::string &Name = ItinsDef->getName();
573
574    // Get the itinerary list for the processor.
575    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
576    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
577
578    OS << "\n";
579    OS << "static const llvm::InstrItinerary ";
580    if (ItinList.empty()) {
581      OS << '*' << Name << " = 0;\n";
582      continue;
583    }
584
585    // Begin processor itinerary table
586    OS << Name << "[] = {\n";
587
588    // For each itinerary class in CodeGenSchedClass::Index order.
589    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
590      InstrItinerary &Intinerary = ItinList[j];
591
592      // Emit Itinerary in the form of
593      // { firstStage, lastStage, firstCycle, lastCycle } // index
594      OS << "  { " <<
595        Intinerary.NumMicroOps << ", " <<
596        Intinerary.FirstStage << ", " <<
597        Intinerary.LastStage << ", " <<
598        Intinerary.FirstOperandCycle << ", " <<
599        Intinerary.LastOperandCycle << " }" <<
600        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
601    }
602    // End processor itinerary table
603    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
604    OS << "};\n";
605  }
606}
607
608// Emit either the value defined in the TableGen Record, or the default
609// value defined in the C++ header. The Record is null if the processor does not
610// define a model.
611void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
612                                         const char *Name, char Separator) {
613  OS << "  ";
614  int V = R ? R->getValueAsInt(Name) : -1;
615  if (V >= 0)
616    OS << V << Separator << " // " << Name;
617  else
618    OS << "MCSchedModel::Default" << Name << Separator;
619  OS << '\n';
620}
621
622void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
623                                              raw_ostream &OS) {
624  char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
625
626  OS << "\n// {Name, NumUnits, SuperIdx, IsBuffered}\n";
627  OS << "static const llvm::MCProcResourceDesc "
628     << ProcModel.ModelName << "ProcResources" << "[] = {\n"
629     << "  {DBGFIELD(\"InvalidUnit\")     0, 0, 0}" << Sep << "\n";
630
631  for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
632    Record *PRDef = ProcModel.ProcResourceDefs[i];
633
634    // Find the SuperIdx
635    unsigned SuperIdx = 0;
636    Record *SuperDef = 0;
637    if (PRDef->getValueInit("Super")->isComplete()) {
638      SuperDef =
639        SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
640      SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
641    }
642    // Emit the ProcResourceDesc
643    if (i+1 == e)
644      Sep = ' ';
645    OS << "  {DBGFIELD(\"" << PRDef->getName() << "\") ";
646    if (PRDef->getName().size() < 15)
647      OS.indent(15 - PRDef->getName().size());
648    OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx << ", "
649       << PRDef->getValueAsBit("Buffered") << "}" << Sep << " // #" << i+1;
650    if (SuperDef)
651      OS << ", Super=" << SuperDef->getName();
652    OS << "\n";
653  }
654  OS << "};\n";
655}
656
657// Find the WriteRes Record that defines processor resources for this
658// SchedWrite.
659Record *SubtargetEmitter::FindWriteResources(
660  const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
661
662  // Check if the SchedWrite is already subtarget-specific and directly
663  // specifies a set of processor resources.
664  if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
665    return SchedWrite.TheDef;
666
667  Record *AliasDef = 0;
668  for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
669       AI != AE; ++AI) {
670    const CodeGenSchedRW &AliasRW =
671      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
672    if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
673      Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
674      if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
675        continue;
676    }
677    if (AliasDef)
678      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
679                    "defined for processor " + ProcModel.ModelName +
680                    " Ensure only one SchedAlias exists per RW.");
681    AliasDef = AliasRW.TheDef;
682  }
683  if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
684    return AliasDef;
685
686  // Check this processor's list of write resources.
687  Record *ResDef = 0;
688  for (RecIter WRI = ProcModel.WriteResDefs.begin(),
689         WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
690    if (!(*WRI)->isSubClassOf("WriteRes"))
691      continue;
692    if (AliasDef == (*WRI)->getValueAsDef("WriteType")
693        || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
694      if (ResDef) {
695        throw TGError((*WRI)->getLoc(), "Resources are defined for both "
696                      "SchedWrite and its alias on processor " +
697                      ProcModel.ModelName);
698      }
699      ResDef = *WRI;
700    }
701  }
702  // TODO: If ProcModel has a base model (previous generation processor),
703  // then call FindWriteResources recursively with that model here.
704  if (!ResDef) {
705    throw TGError(ProcModel.ModelDef->getLoc(),
706                  std::string("Processor does not define resources for ")
707                  + SchedWrite.TheDef->getName());
708  }
709  return ResDef;
710}
711
712/// Find the ReadAdvance record for the given SchedRead on this processor or
713/// return NULL.
714Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
715                                          const CodeGenProcModel &ProcModel) {
716  // Check for SchedReads that directly specify a ReadAdvance.
717  if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
718    return SchedRead.TheDef;
719
720  // Check this processor's list of aliases for SchedRead.
721  Record *AliasDef = 0;
722  for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
723       AI != AE; ++AI) {
724    const CodeGenSchedRW &AliasRW =
725      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
726    if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
727      Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
728      if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
729        continue;
730    }
731    if (AliasDef)
732      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
733                    "defined for processor " + ProcModel.ModelName +
734                    " Ensure only one SchedAlias exists per RW.");
735    AliasDef = AliasRW.TheDef;
736  }
737  if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
738    return AliasDef;
739
740  // Check this processor's ReadAdvanceList.
741  Record *ResDef = 0;
742  for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
743         RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
744    if (!(*RAI)->isSubClassOf("ReadAdvance"))
745      continue;
746    if (AliasDef == (*RAI)->getValueAsDef("ReadType")
747        || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
748      if (ResDef) {
749        throw TGError((*RAI)->getLoc(), "Resources are defined for both "
750                      "SchedRead and its alias on processor " +
751                      ProcModel.ModelName);
752      }
753      ResDef = *RAI;
754    }
755  }
756  // TODO: If ProcModel has a base model (previous generation processor),
757  // then call FindReadAdvance recursively with that model here.
758  if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
759    throw TGError(ProcModel.ModelDef->getLoc(),
760                  std::string("Processor does not define resources for ")
761                  + SchedRead.TheDef->getName());
762  }
763  return ResDef;
764}
765
766// Generate the SchedClass table for this processor and update global
767// tables. Must be called for each processor in order.
768void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
769                                           SchedClassTables &SchedTables) {
770  SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
771  if (!ProcModel.hasInstrSchedModel())
772    return;
773
774  std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
775  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
776         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
777    DEBUG(SCI->dump(&SchedModels));
778
779    SCTab.resize(SCTab.size() + 1);
780    MCSchedClassDesc &SCDesc = SCTab.back();
781    // SCDesc.Name is guarded by NDEBUG
782    SCDesc.NumMicroOps = 0;
783    SCDesc.BeginGroup = false;
784    SCDesc.EndGroup = false;
785    SCDesc.WriteProcResIdx = 0;
786    SCDesc.WriteLatencyIdx = 0;
787    SCDesc.ReadAdvanceIdx = 0;
788
789    // A Variant SchedClass has no resources of its own.
790    if (!SCI->Transitions.empty()) {
791      SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
792      continue;
793    }
794
795    // Determine if the SchedClass is actually reachable on this processor. If
796    // not don't try to locate the processor resources, it will fail.
797    // If ProcIndices contains 0, this class applies to all processors.
798    assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
799    if (SCI->ProcIndices[0] != 0) {
800      IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
801                                SCI->ProcIndices.end(), ProcModel.Index);
802      if (PIPos == SCI->ProcIndices.end())
803        continue;
804    }
805    IdxVec Writes = SCI->Writes;
806    IdxVec Reads = SCI->Reads;
807    if (SCI->ItinClassDef) {
808      assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs");
809      // Check this processor's itinerary class resources.
810      for (RecIter II = ProcModel.ItinRWDefs.begin(),
811             IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
812        RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
813        if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
814            != Matched.end()) {
815          SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
816                              Writes, Reads);
817          break;
818        }
819      }
820      if (Writes.empty()) {
821        DEBUG(dbgs() << ProcModel.ItinsDef->getName()
822              << " does not have resources for itinerary class "
823              << SCI->ItinClassDef->getName() << '\n');
824      }
825    }
826    else if (!SCI->InstRWs.empty()) {
827      // This class may have a default ReadWrite list which can be overriden by
828      // InstRW definitions.
829      Record *RWDef = 0;
830      for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
831           RWI != RWE; ++RWI) {
832        Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
833        if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
834          RWDef = *RWI;
835          break;
836        }
837      }
838      if (RWDef) {
839        Writes.clear();
840        Reads.clear();
841        SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
842                            Writes, Reads);
843      }
844    }
845    // Sum resources across all operand writes.
846    std::vector<MCWriteProcResEntry> WriteProcResources;
847    std::vector<MCWriteLatencyEntry> WriteLatencies;
848    std::vector<std::string> WriterNames;
849    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
850    for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
851      IdxVec WriteSeq;
852      SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
853                                     ProcModel);
854
855      // For each operand, create a latency entry.
856      MCWriteLatencyEntry WLEntry;
857      WLEntry.Cycles = 0;
858      unsigned WriteID = WriteSeq.back();
859      WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
860      // If this Write is not referenced by a ReadAdvance, don't distinguish it
861      // from other WriteLatency entries.
862      if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) {
863        WriteID = 0;
864      }
865      WLEntry.WriteResourceID = WriteID;
866
867      for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
868           WSI != WSE; ++WSI) {
869
870        Record *WriteRes =
871          FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
872
873        // Mark the parent class as invalid for unsupported write types.
874        if (WriteRes->getValueAsBit("Unsupported")) {
875          SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
876          break;
877        }
878        WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
879        SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
880        SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
881        SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
882
883        // Create an entry for each ProcResource listed in WriteRes.
884        RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
885        std::vector<int64_t> Cycles =
886          WriteRes->getValueAsListOfInts("ResourceCycles");
887        for (unsigned PRIdx = 0, PREnd = PRVec.size();
888             PRIdx != PREnd; ++PRIdx) {
889          MCWriteProcResEntry WPREntry;
890          WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
891          assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
892          if (Cycles.size() > PRIdx)
893            WPREntry.Cycles = Cycles[PRIdx];
894          else
895            WPREntry.Cycles = 1;
896          WriteProcResources.push_back(WPREntry);
897        }
898      }
899      WriteLatencies.push_back(WLEntry);
900    }
901    // Create an entry for each operand Read in this SchedClass.
902    // Entries must be sorted first by UseIdx then by WriteResourceID.
903    for (unsigned UseIdx = 0, EndIdx = Reads.size();
904         UseIdx != EndIdx; ++UseIdx) {
905      Record *ReadAdvance =
906        FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
907      if (!ReadAdvance)
908        continue;
909
910      // Mark the parent class as invalid for unsupported write types.
911      if (ReadAdvance->getValueAsBit("Unsupported")) {
912        SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
913        break;
914      }
915      RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
916      IdxVec WriteIDs;
917      if (ValidWrites.empty())
918        WriteIDs.push_back(0);
919      else {
920        for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
921             VWI != VWE; ++VWI) {
922          WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
923        }
924      }
925      std::sort(WriteIDs.begin(), WriteIDs.end());
926      for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
927        MCReadAdvanceEntry RAEntry;
928        RAEntry.UseIdx = UseIdx;
929        RAEntry.WriteResourceID = *WI;
930        RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
931        ReadAdvanceEntries.push_back(RAEntry);
932      }
933    }
934    if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
935      WriteProcResources.clear();
936      WriteLatencies.clear();
937      ReadAdvanceEntries.clear();
938    }
939    // Add the information for this SchedClass to the global tables using basic
940    // compression.
941    //
942    // WritePrecRes entries are sorted by ProcResIdx.
943    std::sort(WriteProcResources.begin(), WriteProcResources.end(),
944              LessWriteProcResources());
945
946    SCDesc.NumWriteProcResEntries = WriteProcResources.size();
947    std::vector<MCWriteProcResEntry>::iterator WPRPos =
948      std::search(SchedTables.WriteProcResources.begin(),
949                  SchedTables.WriteProcResources.end(),
950                  WriteProcResources.begin(), WriteProcResources.end());
951    if (WPRPos != SchedTables.WriteProcResources.end())
952      SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
953    else {
954      SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
955      SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
956                                            WriteProcResources.end());
957    }
958    // Latency entries must remain in operand order.
959    SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
960    std::vector<MCWriteLatencyEntry>::iterator WLPos =
961      std::search(SchedTables.WriteLatencies.begin(),
962                  SchedTables.WriteLatencies.end(),
963                  WriteLatencies.begin(), WriteLatencies.end());
964    if (WLPos != SchedTables.WriteLatencies.end()) {
965      unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
966      SCDesc.WriteLatencyIdx = idx;
967      for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
968        if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
969            std::string::npos) {
970          SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
971        }
972    }
973    else {
974      SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
975      SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
976                                        WriteLatencies.begin(),
977                                        WriteLatencies.end());
978      SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
979                                     WriterNames.begin(), WriterNames.end());
980    }
981    // ReadAdvanceEntries must remain in operand order.
982    SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
983    std::vector<MCReadAdvanceEntry>::iterator RAPos =
984      std::search(SchedTables.ReadAdvanceEntries.begin(),
985                  SchedTables.ReadAdvanceEntries.end(),
986                  ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
987    if (RAPos != SchedTables.ReadAdvanceEntries.end())
988      SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
989    else {
990      SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
991      SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
992                                            ReadAdvanceEntries.end());
993    }
994  }
995}
996
997// Emit SchedClass tables for all processors and associated global tables.
998void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
999                                            raw_ostream &OS) {
1000  // Emit global WriteProcResTable.
1001  OS << "\n// {ProcResourceIdx, Cycles}\n"
1002     << "extern const llvm::MCWriteProcResEntry "
1003     << Target << "WriteProcResTable[] = {\n"
1004     << "  { 0,  0}, // Invalid\n";
1005  for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
1006       WPRIdx != WPREnd; ++WPRIdx) {
1007    MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
1008    OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
1009       << format("%2d", WPREntry.Cycles) << "}";
1010    if (WPRIdx + 1 < WPREnd)
1011      OS << ',';
1012    OS << " // #" << WPRIdx << '\n';
1013  }
1014  OS << "}; // " << Target << "WriteProcResTable\n";
1015
1016  // Emit global WriteLatencyTable.
1017  OS << "\n// {Cycles, WriteResourceID}\n"
1018     << "extern const llvm::MCWriteLatencyEntry "
1019     << Target << "WriteLatencyTable[] = {\n"
1020     << "  { 0,  0}, // Invalid\n";
1021  for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
1022       WLIdx != WLEnd; ++WLIdx) {
1023    MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
1024    OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
1025       << format("%2d", WLEntry.WriteResourceID) << "}";
1026    if (WLIdx + 1 < WLEnd)
1027      OS << ',';
1028    OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
1029  }
1030  OS << "}; // " << Target << "WriteLatencyTable\n";
1031
1032  // Emit global ReadAdvanceTable.
1033  OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
1034     << "extern const llvm::MCReadAdvanceEntry "
1035     << Target << "ReadAdvanceTable[] = {\n"
1036     << "  {0,  0,  0}, // Invalid\n";
1037  for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
1038       RAIdx != RAEnd; ++RAIdx) {
1039    MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
1040    OS << "  {" << RAEntry.UseIdx << ", "
1041       << format("%2d", RAEntry.WriteResourceID) << ", "
1042       << format("%2d", RAEntry.Cycles) << "}";
1043    if (RAIdx + 1 < RAEnd)
1044      OS << ',';
1045    OS << " // #" << RAIdx << '\n';
1046  }
1047  OS << "}; // " << Target << "ReadAdvanceTable\n";
1048
1049  // Emit a SchedClass table for each processor.
1050  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1051         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1052    if (!PI->hasInstrSchedModel())
1053      continue;
1054
1055    std::vector<MCSchedClassDesc> &SCTab =
1056      SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()];
1057
1058    OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
1059       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
1060    OS << "static const llvm::MCSchedClassDesc "
1061       << PI->ModelName << "SchedClasses[] = {\n";
1062
1063    // The first class is always invalid. We no way to distinguish it except by
1064    // name and position.
1065    assert(SchedModels.getSchedClass(0).Name == "NoItinerary"
1066           && "invalid class not first");
1067    OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
1068       << MCSchedClassDesc::InvalidNumMicroOps
1069       << ", 0, 0,  0, 0,  0, 0,  0, 0},\n";
1070
1071    for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
1072      MCSchedClassDesc &MCDesc = SCTab[SCIdx];
1073      const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
1074      OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
1075      if (SchedClass.Name.size() < 18)
1076        OS.indent(18 - SchedClass.Name.size());
1077      OS << MCDesc.NumMicroOps
1078         << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
1079         << ", " << format("%2d", MCDesc.WriteProcResIdx)
1080         << ", " << MCDesc.NumWriteProcResEntries
1081         << ", " << format("%2d", MCDesc.WriteLatencyIdx)
1082         << ", " << MCDesc.NumWriteLatencyEntries
1083         << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
1084         << ", " << MCDesc.NumReadAdvanceEntries << "}";
1085      if (SCIdx + 1 < SCEnd)
1086        OS << ',';
1087      OS << " // #" << SCIdx << '\n';
1088    }
1089    OS << "}; // " << PI->ModelName << "SchedClasses\n";
1090  }
1091}
1092
1093void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
1094  // For each processor model.
1095  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1096         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1097    // Emit processor resource table.
1098    if (PI->hasInstrSchedModel())
1099      EmitProcessorResources(*PI, OS);
1100    else if(!PI->ProcResourceDefs.empty())
1101      throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
1102                    "ProcResources without defining WriteRes SchedWriteRes");
1103
1104    // Begin processor itinerary properties
1105    OS << "\n";
1106    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
1107    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
1108    EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
1109    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
1110    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1111    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1112    OS << "  " << PI->Index << ", // Processor ID\n";
1113    if (PI->hasInstrSchedModel())
1114      OS << "  " << PI->ModelName << "ProcResources" << ",\n"
1115         << "  " << PI->ModelName << "SchedClasses" << ",\n"
1116         << "  " << PI->ProcResourceDefs.size()+1 << ",\n"
1117         << "  " << (SchedModels.schedClassEnd()
1118                     - SchedModels.schedClassBegin()) << ",\n";
1119    else
1120      OS << "  0, 0, 0, 0, // No instruction-level machine model.\n";
1121    if (SchedModels.hasItineraryClasses())
1122      OS << "  " << PI->ItinsDef->getName() << ");\n";
1123    else
1124      OS << "  0); // No Itinerary\n";
1125  }
1126}
1127
1128//
1129// EmitProcessorLookup - generate cpu name to itinerary lookup table.
1130//
1131void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
1132  // Gather and sort processor information
1133  std::vector<Record*> ProcessorList =
1134                          Records.getAllDerivedDefinitions("Processor");
1135  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
1136
1137  // Begin processor table
1138  OS << "\n";
1139  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
1140     << "extern const llvm::SubtargetInfoKV "
1141     << Target << "ProcSchedKV[] = {\n";
1142
1143  // For each processor
1144  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
1145    // Next processor
1146    Record *Processor = ProcessorList[i];
1147
1148    const std::string &Name = Processor->getValueAsString("Name");
1149    const std::string &ProcModelName =
1150      SchedModels.getModelForProc(Processor).ModelName;
1151
1152    // Emit as { "cpu", procinit },
1153    OS << "  { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
1154
1155    // Depending on ''if more in the list'' emit comma
1156    if (++i < N) OS << ",";
1157
1158    OS << "\n";
1159  }
1160
1161  // End processor table
1162  OS << "};\n";
1163}
1164
1165//
1166// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
1167//
1168void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
1169  OS << "#ifdef DBGFIELD\n"
1170     << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
1171     << "#endif\n"
1172     << "#ifndef NDEBUG\n"
1173     << "#define DBGFIELD(x) x,\n"
1174     << "#else\n"
1175     << "#define DBGFIELD(x)\n"
1176     << "#endif\n";
1177
1178  if (SchedModels.hasItineraryClasses()) {
1179    std::vector<std::vector<InstrItinerary> > ProcItinLists;
1180    // Emit the stage data
1181    EmitStageAndOperandCycleData(OS, ProcItinLists);
1182    EmitItineraries(OS, ProcItinLists);
1183  }
1184  OS << "\n// ===============================================================\n"
1185     << "// Data tables for the new per-operand machine model.\n";
1186
1187  SchedClassTables SchedTables;
1188  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1189         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1190    GenSchedClassTables(*PI, SchedTables);
1191  }
1192  EmitSchedClassTables(SchedTables, OS);
1193
1194  // Emit the processor machine model
1195  EmitProcessorModels(OS);
1196  // Emit the processor lookup data
1197  EmitProcessorLookup(OS);
1198
1199  OS << "#undef DBGFIELD";
1200}
1201
1202void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
1203                                             raw_ostream &OS) {
1204  OS << "unsigned " << ClassName
1205     << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
1206     << " const TargetSchedModel *SchedModel) const {\n";
1207
1208  std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
1209  std::sort(Prologs.begin(), Prologs.end(), LessRecord());
1210  for (std::vector<Record*>::const_iterator
1211         PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
1212    OS << (*PI)->getValueAsString("Code") << '\n';
1213  }
1214  IdxVec VariantClasses;
1215  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
1216         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
1217    if (SCI->Transitions.empty())
1218      continue;
1219    VariantClasses.push_back(SCI - SchedModels.schedClassBegin());
1220  }
1221  if (!VariantClasses.empty()) {
1222    OS << "  switch (SchedClass) {\n";
1223    for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
1224         VCI != VCE; ++VCI) {
1225      const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
1226      OS << "  case " << *VCI << ": // " << SC.Name << '\n';
1227      IdxVec ProcIndices;
1228      for (std::vector<CodeGenSchedTransition>::const_iterator
1229             TI = SC.Transitions.begin(), TE = SC.Transitions.end();
1230           TI != TE; ++TI) {
1231        IdxVec PI;
1232        std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
1233                       ProcIndices.begin(), ProcIndices.end(),
1234                       std::back_inserter(PI));
1235        ProcIndices.swap(PI);
1236      }
1237      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
1238           PI != PE; ++PI) {
1239        OS << "    ";
1240        if (*PI != 0)
1241          OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
1242        OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
1243           << '\n';
1244        for (std::vector<CodeGenSchedTransition>::const_iterator
1245               TI = SC.Transitions.begin(), TE = SC.Transitions.end();
1246             TI != TE; ++TI) {
1247          OS << "      if (";
1248          if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
1249                                      TI->ProcIndices.end(), *PI)) {
1250              continue;
1251          }
1252          for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
1253               RI != RE; ++RI) {
1254            if (RI != TI->PredTerm.begin())
1255              OS << "\n          && ";
1256            OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
1257          }
1258          OS << ")\n"
1259             << "        return " << TI->ToClassIdx << "; // "
1260             << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
1261        }
1262        OS << "    }\n";
1263        if (*PI == 0)
1264          break;
1265      }
1266      unsigned SCIdx = 0;
1267      if (SC.ItinClassDef)
1268        SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef);
1269      else
1270        SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads);
1271      if (SCIdx != *VCI)
1272        OS << "    return " << SCIdx << ";\n";
1273      OS << "    break;\n";
1274    }
1275    OS << "  };\n";
1276  }
1277  OS << "  report_fatal_error(\"Expected a variant SchedClass\");\n"
1278     << "} // " << ClassName << "::resolveSchedClass\n";
1279}
1280
1281//
1282// ParseFeaturesFunction - Produces a subtarget specific function for parsing
1283// the subtarget features string.
1284//
1285void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
1286                                             unsigned NumFeatures,
1287                                             unsigned NumProcs) {
1288  std::vector<Record*> Features =
1289                       Records.getAllDerivedDefinitions("SubtargetFeature");
1290  std::sort(Features.begin(), Features.end(), LessRecord());
1291
1292  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1293     << "// subtarget options.\n"
1294     << "void llvm::";
1295  OS << Target;
1296  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1297     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
1298     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
1299
1300  if (Features.empty()) {
1301    OS << "}\n";
1302    return;
1303  }
1304
1305  OS << "  InitMCProcessorInfo(CPU, FS);\n"
1306     << "  uint64_t Bits = getFeatureBits();\n";
1307
1308  for (unsigned i = 0; i < Features.size(); i++) {
1309    // Next record
1310    Record *R = Features[i];
1311    const std::string &Instance = R->getName();
1312    const std::string &Value = R->getValueAsString("Value");
1313    const std::string &Attribute = R->getValueAsString("Attribute");
1314
1315    if (Value=="true" || Value=="false")
1316      OS << "  if ((Bits & " << Target << "::"
1317         << Instance << ") != 0) "
1318         << Attribute << " = " << Value << ";\n";
1319    else
1320      OS << "  if ((Bits & " << Target << "::"
1321         << Instance << ") != 0 && "
1322         << Attribute << " < " << Value << ") "
1323         << Attribute << " = " << Value << ";\n";
1324  }
1325
1326  OS << "}\n";
1327}
1328
1329//
1330// SubtargetEmitter::run - Main subtarget enumeration emitter.
1331//
1332void SubtargetEmitter::run(raw_ostream &OS) {
1333  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1334
1335  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1336  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1337
1338  OS << "namespace llvm {\n";
1339  Enumeration(OS, "SubtargetFeature", true);
1340  OS << "} // End llvm namespace \n";
1341  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1342
1343  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
1344  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1345
1346  OS << "namespace llvm {\n";
1347#if 0
1348  OS << "namespace {\n";
1349#endif
1350  unsigned NumFeatures = FeatureKeyValues(OS);
1351  OS << "\n";
1352  unsigned NumProcs = CPUKeyValues(OS);
1353  OS << "\n";
1354  EmitSchedModel(OS);
1355  OS << "\n";
1356#if 0
1357  OS << "}\n";
1358#endif
1359
1360  // MCInstrInfo initialization routine.
1361  OS << "static inline void Init" << Target
1362     << "MCSubtargetInfo(MCSubtargetInfo *II, "
1363     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
1364  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
1365  if (NumFeatures)
1366    OS << Target << "FeatureKV, ";
1367  else
1368    OS << "0, ";
1369  if (NumProcs)
1370    OS << Target << "SubTypeKV, ";
1371  else
1372    OS << "0, ";
1373  OS << '\n'; OS.indent(22);
1374  OS << Target << "ProcSchedKV, "
1375     << Target << "WriteProcResTable, "
1376     << Target << "WriteLatencyTable, "
1377     << Target << "ReadAdvanceTable, ";
1378  if (SchedModels.hasItineraryClasses()) {
1379    OS << '\n'; OS.indent(22);
1380    OS << Target << "Stages, "
1381       << Target << "OperandCycles, "
1382       << Target << "ForwardingPaths, ";
1383  } else
1384    OS << "0, 0, 0, ";
1385  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1386
1387  OS << "} // End llvm namespace \n";
1388
1389  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
1390
1391  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
1392  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
1393
1394  OS << "#include \"llvm/Support/Debug.h\"\n";
1395  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
1396  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
1397
1398  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
1399
1400  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
1401  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
1402  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
1403
1404  std::string ClassName = Target + "GenSubtargetInfo";
1405  OS << "namespace llvm {\n";
1406  OS << "class DFAPacketizer;\n";
1407  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
1408     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
1409     << "StringRef FS);\n"
1410     << "public:\n"
1411     << "  unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI,"
1412     << " const TargetSchedModel *SchedModel) const;\n"
1413     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1414     << " const;\n"
1415     << "};\n";
1416  OS << "} // End llvm namespace \n";
1417
1418  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
1419
1420  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
1421  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
1422
1423  OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
1424  OS << "namespace llvm {\n";
1425  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
1426  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1427  OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1428  OS << "extern const llvm::MCWriteProcResEntry "
1429     << Target << "WriteProcResTable[];\n";
1430  OS << "extern const llvm::MCWriteLatencyEntry "
1431     << Target << "WriteLatencyTable[];\n";
1432  OS << "extern const llvm::MCReadAdvanceEntry "
1433     << Target << "ReadAdvanceTable[];\n";
1434
1435  if (SchedModels.hasItineraryClasses()) {
1436    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
1437    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1438    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1439  }
1440
1441  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
1442     << "StringRef FS)\n"
1443     << "  : TargetSubtargetInfo() {\n"
1444     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
1445  if (NumFeatures)
1446    OS << Target << "FeatureKV, ";
1447  else
1448    OS << "0, ";
1449  if (NumProcs)
1450    OS << Target << "SubTypeKV, ";
1451  else
1452    OS << "0, ";
1453  OS << '\n'; OS.indent(22);
1454  OS << Target << "ProcSchedKV, "
1455     << Target << "WriteProcResTable, "
1456     << Target << "WriteLatencyTable, "
1457     << Target << "ReadAdvanceTable, ";
1458  OS << '\n'; OS.indent(22);
1459  if (SchedModels.hasItineraryClasses()) {
1460    OS << Target << "Stages, "
1461       << Target << "OperandCycles, "
1462       << Target << "ForwardingPaths, ";
1463  } else
1464    OS << "0, 0, 0, ";
1465  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1466
1467  EmitSchedModelHelpers(ClassName, OS);
1468
1469  OS << "} // End llvm namespace \n";
1470
1471  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1472}
1473
1474namespace llvm {
1475
1476void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
1477  CodeGenTarget CGTarget(RK);
1478  SubtargetEmitter(RK, CGTarget).run(OS);
1479}
1480
1481} // End llvm namespace
1482