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