Home | History | Annotate | Line # | Download | only in TableGen
      1 //===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file defines structures to encapsulate the machine model as described in
     10 // the target description.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
     15 #define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
     16 
     17 #include "llvm/ADT/APInt.h"
     18 #include "llvm/ADT/DenseMap.h"
     19 #include "llvm/ADT/STLExtras.h"
     20 #include "llvm/ADT/StringMap.h"
     21 #include "llvm/Support/ErrorHandling.h"
     22 #include "llvm/TableGen/Record.h"
     23 #include "llvm/TableGen/SetTheory.h"
     24 #include <map>
     25 
     26 namespace llvm {
     27 
     28 class CodeGenTarget;
     29 class CodeGenSchedModels;
     30 class CodeGenInstruction;
     31 class CodeGenRegisterClass;
     32 
     33 using RecVec = std::vector<Record*>;
     34 using RecIter = std::vector<Record*>::const_iterator;
     35 
     36 using IdxVec = std::vector<unsigned>;
     37 using IdxIter = std::vector<unsigned>::const_iterator;
     38 
     39 /// We have two kinds of SchedReadWrites. Explicitly defined and inferred
     40 /// sequences.  TheDef is nonnull for explicit SchedWrites, but Sequence may or
     41 /// may not be empty. TheDef is null for inferred sequences, and Sequence must
     42 /// be nonempty.
     43 ///
     44 /// IsVariadic controls whether the variants are expanded into multiple operands
     45 /// or a sequence of writes on one operand.
     46 struct CodeGenSchedRW {
     47   unsigned Index;
     48   std::string Name;
     49   Record *TheDef;
     50   bool IsRead;
     51   bool IsAlias;
     52   bool HasVariants;
     53   bool IsVariadic;
     54   bool IsSequence;
     55   IdxVec Sequence;
     56   RecVec Aliases;
     57 
     58   CodeGenSchedRW()
     59     : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false),
     60       HasVariants(false), IsVariadic(false), IsSequence(false) {}
     61   CodeGenSchedRW(unsigned Idx, Record *Def)
     62     : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {
     63     Name = std::string(Def->getName());
     64     IsRead = Def->isSubClassOf("SchedRead");
     65     HasVariants = Def->isSubClassOf("SchedVariant");
     66     if (HasVariants)
     67       IsVariadic = Def->getValueAsBit("Variadic");
     68 
     69     // Read records don't currently have sequences, but it can be easily
     70     // added. Note that implicit Reads (from ReadVariant) may have a Sequence
     71     // (but no record).
     72     IsSequence = Def->isSubClassOf("WriteSequence");
     73   }
     74 
     75   CodeGenSchedRW(unsigned Idx, bool Read, ArrayRef<unsigned> Seq,
     76                  const std::string &Name)
     77       : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false),
     78         HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
     79     assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
     80   }
     81 
     82   bool isValid() const {
     83     assert((!HasVariants || TheDef) && "Variant write needs record def");
     84     assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
     85     assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
     86     assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
     87     assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
     88     return TheDef || !Sequence.empty();
     89   }
     90 
     91 #ifndef NDEBUG
     92   void dump() const;
     93 #endif
     94 };
     95 
     96 /// Represent a transition between SchedClasses induced by SchedVariant.
     97 struct CodeGenSchedTransition {
     98   unsigned ToClassIdx;
     99   unsigned ProcIndex;
    100   RecVec PredTerm;
    101 };
    102 
    103 /// Scheduling class.
    104 ///
    105 /// Each instruction description will be mapped to a scheduling class. There are
    106 /// four types of classes:
    107 ///
    108 /// 1) An explicitly defined itinerary class with ItinClassDef set.
    109 /// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor.
    110 ///
    111 /// 2) An implied class with a list of SchedWrites and SchedReads that are
    112 /// defined in an instruction definition and which are common across all
    113 /// subtargets. ProcIndices contains 0 for any processor.
    114 ///
    115 /// 3) An implied class with a list of InstRW records that map instructions to
    116 /// SchedWrites and SchedReads per-processor. InstrClassMap should map the same
    117 /// instructions to this class. ProcIndices contains all the processors that
    118 /// provided InstrRW records for this class. ItinClassDef or Writes/Reads may
    119 /// still be defined for processors with no InstRW entry.
    120 ///
    121 /// 4) An inferred class represents a variant of another class that may be
    122 /// resolved at runtime. ProcIndices contains the set of processors that may
    123 /// require the class. ProcIndices are propagated through SchedClasses as
    124 /// variants are expanded. Multiple SchedClasses may be inferred from an
    125 /// itinerary class. Each inherits the processor index from the ItinRW record
    126 /// that mapped the itinerary class to the variant Writes or Reads.
    127 struct CodeGenSchedClass {
    128   unsigned Index;
    129   std::string Name;
    130   Record *ItinClassDef;
    131 
    132   IdxVec Writes;
    133   IdxVec Reads;
    134   // Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
    135   IdxVec ProcIndices;
    136 
    137   std::vector<CodeGenSchedTransition> Transitions;
    138 
    139   // InstRW records associated with this class. These records may refer to an
    140   // Instruction no longer mapped to this class by InstrClassMap. These
    141   // Instructions should be ignored by this class because they have been split
    142   // off to join another inferred class.
    143   RecVec InstRWs;
    144   // InstRWs processor indices. Filled in inferFromInstRWs
    145   DenseSet<unsigned> InstRWProcIndices;
    146 
    147   CodeGenSchedClass(unsigned Index, std::string Name, Record *ItinClassDef)
    148     : Index(Index), Name(std::move(Name)), ItinClassDef(ItinClassDef) {}
    149 
    150   bool isKeyEqual(Record *IC, ArrayRef<unsigned> W,
    151                   ArrayRef<unsigned> R) const {
    152     return ItinClassDef == IC && makeArrayRef(Writes) == W &&
    153            makeArrayRef(Reads) == R;
    154   }
    155 
    156   // Is this class generated from a variants if existing classes? Instructions
    157   // are never mapped directly to inferred scheduling classes.
    158   bool isInferred() const { return !ItinClassDef; }
    159 
    160 #ifndef NDEBUG
    161   void dump(const CodeGenSchedModels *SchedModels) const;
    162 #endif
    163 };
    164 
    165 /// Represent the cost of allocating a register of register class RCDef.
    166 ///
    167 /// The cost of allocating a register is equivalent to the number of physical
    168 /// registers used by the register renamer. Register costs are defined at
    169 /// register class granularity.
    170 struct CodeGenRegisterCost {
    171   Record *RCDef;
    172   unsigned Cost;
    173   bool AllowMoveElimination;
    174   CodeGenRegisterCost(Record *RC, unsigned RegisterCost, bool AllowMoveElim = false)
    175       : RCDef(RC), Cost(RegisterCost), AllowMoveElimination(AllowMoveElim) {}
    176   CodeGenRegisterCost(const CodeGenRegisterCost &) = default;
    177   CodeGenRegisterCost &operator=(const CodeGenRegisterCost &) = delete;
    178 };
    179 
    180 /// A processor register file.
    181 ///
    182 /// This class describes a processor register file. Register file information is
    183 /// currently consumed by external tools like llvm-mca to predict dispatch
    184 /// stalls due to register pressure.
    185 struct CodeGenRegisterFile {
    186   std::string Name;
    187   Record *RegisterFileDef;
    188   unsigned MaxMovesEliminatedPerCycle;
    189   bool AllowZeroMoveEliminationOnly;
    190 
    191   unsigned NumPhysRegs;
    192   std::vector<CodeGenRegisterCost> Costs;
    193 
    194   CodeGenRegisterFile(StringRef name, Record *def, unsigned MaxMoveElimPerCy = 0,
    195                       bool AllowZeroMoveElimOnly = false)
    196       : Name(name), RegisterFileDef(def),
    197         MaxMovesEliminatedPerCycle(MaxMoveElimPerCy),
    198         AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly),
    199         NumPhysRegs(0) {}
    200 
    201   bool hasDefaultCosts() const { return Costs.empty(); }
    202 };
    203 
    204 // Processor model.
    205 //
    206 // ModelName is a unique name used to name an instantiation of MCSchedModel.
    207 //
    208 // ModelDef is NULL for inferred Models. This happens when a processor defines
    209 // an itinerary but no machine model. If the processor defines neither a machine
    210 // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
    211 // the special "NoModel" field set to true.
    212 //
    213 // ItinsDef always points to a valid record definition, but may point to the
    214 // default NoItineraries. NoItineraries has an empty list of InstrItinData
    215 // records.
    216 //
    217 // ItinDefList orders this processor's InstrItinData records by SchedClass idx.
    218 struct CodeGenProcModel {
    219   unsigned Index;
    220   std::string ModelName;
    221   Record *ModelDef;
    222   Record *ItinsDef;
    223 
    224   // Derived members...
    225 
    226   // Array of InstrItinData records indexed by a CodeGenSchedClass index.
    227   // This list is empty if the Processor has no value for Itineraries.
    228   // Initialized by collectProcItins().
    229   RecVec ItinDefList;
    230 
    231   // Map itinerary classes to per-operand resources.
    232   // This list is empty if no ItinRW refers to this Processor.
    233   RecVec ItinRWDefs;
    234 
    235   // List of unsupported feature.
    236   // This list is empty if the Processor has no UnsupportedFeatures.
    237   RecVec UnsupportedFeaturesDefs;
    238 
    239   // All read/write resources associated with this processor.
    240   RecVec WriteResDefs;
    241   RecVec ReadAdvanceDefs;
    242 
    243   // Per-operand machine model resources associated with this processor.
    244   RecVec ProcResourceDefs;
    245 
    246   // List of Register Files.
    247   std::vector<CodeGenRegisterFile> RegisterFiles;
    248 
    249   // Optional Retire Control Unit definition.
    250   Record *RetireControlUnit;
    251 
    252   // Load/Store queue descriptors.
    253   Record *LoadQueue;
    254   Record *StoreQueue;
    255 
    256   CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
    257                    Record *IDef) :
    258     Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
    259     RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {}
    260 
    261   bool hasItineraries() const {
    262     return !ItinsDef->getValueAsListOfDefs("IID").empty();
    263   }
    264 
    265   bool hasInstrSchedModel() const {
    266     return !WriteResDefs.empty() || !ItinRWDefs.empty();
    267   }
    268 
    269   bool hasExtraProcessorInfo() const {
    270     return RetireControlUnit || LoadQueue || StoreQueue ||
    271            !RegisterFiles.empty();
    272   }
    273 
    274   unsigned getProcResourceIdx(Record *PRDef) const;
    275 
    276   bool isUnsupported(const CodeGenInstruction &Inst) const;
    277 
    278 #ifndef NDEBUG
    279   void dump() const;
    280 #endif
    281 };
    282 
    283 /// Used to correlate instructions to MCInstPredicates specified by
    284 /// InstructionEquivalentClass tablegen definitions.
    285 ///
    286 /// Example: a XOR of a register with self, is a known zero-idiom for most
    287 /// X86 processors.
    288 ///
    289 /// Each processor can use a (potentially different) InstructionEquivalenceClass
    290 ///  definition to classify zero-idioms. That means, XORrr is likely to appear
    291 /// in more than one equivalence class (where each class definition is
    292 /// contributed by a different processor).
    293 ///
    294 /// There is no guarantee that the same MCInstPredicate will be used to describe
    295 /// equivalence classes that identify XORrr as a zero-idiom.
    296 ///
    297 /// To be more specific, the requirements for being a zero-idiom XORrr may be
    298 /// different for different processors.
    299 ///
    300 /// Class PredicateInfo identifies a subset of processors that specify the same
    301 /// requirements (i.e. same MCInstPredicate and OperandMask) for an instruction
    302 /// opcode.
    303 ///
    304 /// Back to the example. Field `ProcModelMask` will have one bit set for every
    305 /// processor model that sees XORrr as a zero-idiom, and that specifies the same
    306 /// set of constraints.
    307 ///
    308 /// By construction, there can be multiple instances of PredicateInfo associated
    309 /// with a same instruction opcode. For example, different processors may define
    310 /// different constraints on the same opcode.
    311 ///
    312 /// Field OperandMask can be used as an extra constraint.
    313 /// It may be used to describe conditions that appy only to a subset of the
    314 /// operands of a machine instruction, and the operands subset may not be the
    315 /// same for all processor models.
    316 struct PredicateInfo {
    317   llvm::APInt ProcModelMask; // A set of processor model indices.
    318   llvm::APInt OperandMask;   // An operand mask.
    319   const Record *Predicate;   // MCInstrPredicate definition.
    320   PredicateInfo(llvm::APInt CpuMask, llvm::APInt Operands, const Record *Pred)
    321       : ProcModelMask(CpuMask), OperandMask(Operands), Predicate(Pred) {}
    322 
    323   bool operator==(const PredicateInfo &Other) const {
    324     return ProcModelMask == Other.ProcModelMask &&
    325            OperandMask == Other.OperandMask && Predicate == Other.Predicate;
    326   }
    327 };
    328 
    329 /// A collection of PredicateInfo objects.
    330 ///
    331 /// There is at least one OpcodeInfo object for every opcode specified by a
    332 /// TIPredicate definition.
    333 class OpcodeInfo {
    334   std::vector<PredicateInfo> Predicates;
    335 
    336   OpcodeInfo(const OpcodeInfo &Other) = delete;
    337   OpcodeInfo &operator=(const OpcodeInfo &Other) = delete;
    338 
    339 public:
    340   OpcodeInfo() = default;
    341   OpcodeInfo &operator=(OpcodeInfo &&Other) = default;
    342   OpcodeInfo(OpcodeInfo &&Other) = default;
    343 
    344   ArrayRef<PredicateInfo> getPredicates() const { return Predicates; }
    345 
    346   void addPredicateForProcModel(const llvm::APInt &CpuMask,
    347                                 const llvm::APInt &OperandMask,
    348                                 const Record *Predicate);
    349 };
    350 
    351 /// Used to group together tablegen instruction definitions that are subject
    352 /// to a same set of constraints (identified by an instance of OpcodeInfo).
    353 class OpcodeGroup {
    354   OpcodeInfo Info;
    355   std::vector<const Record *> Opcodes;
    356 
    357   OpcodeGroup(const OpcodeGroup &Other) = delete;
    358   OpcodeGroup &operator=(const OpcodeGroup &Other) = delete;
    359 
    360 public:
    361   OpcodeGroup(OpcodeInfo &&OpInfo) : Info(std::move(OpInfo)) {}
    362   OpcodeGroup(OpcodeGroup &&Other) = default;
    363 
    364   void addOpcode(const Record *Opcode) {
    365     assert(!llvm::is_contained(Opcodes, Opcode) && "Opcode already in set!");
    366     Opcodes.push_back(Opcode);
    367   }
    368 
    369   ArrayRef<const Record *> getOpcodes() const { return Opcodes; }
    370   const OpcodeInfo &getOpcodeInfo() const { return Info; }
    371 };
    372 
    373 /// An STIPredicateFunction descriptor used by tablegen backends to
    374 /// auto-generate the body of a predicate function as a member of tablegen'd
    375 /// class XXXGenSubtargetInfo.
    376 class STIPredicateFunction {
    377   const Record *FunctionDeclaration;
    378 
    379   std::vector<const Record *> Definitions;
    380   std::vector<OpcodeGroup> Groups;
    381 
    382   STIPredicateFunction(const STIPredicateFunction &Other) = delete;
    383   STIPredicateFunction &operator=(const STIPredicateFunction &Other) = delete;
    384 
    385 public:
    386   STIPredicateFunction(const Record *Rec) : FunctionDeclaration(Rec) {}
    387   STIPredicateFunction(STIPredicateFunction &&Other) = default;
    388 
    389   bool isCompatibleWith(const STIPredicateFunction &Other) const {
    390     return FunctionDeclaration == Other.FunctionDeclaration;
    391   }
    392 
    393   void addDefinition(const Record *Def) { Definitions.push_back(Def); }
    394   void addOpcode(const Record *OpcodeRec, OpcodeInfo &&Info) {
    395     if (Groups.empty() ||
    396         Groups.back().getOpcodeInfo().getPredicates() != Info.getPredicates())
    397       Groups.emplace_back(std::move(Info));
    398     Groups.back().addOpcode(OpcodeRec);
    399   }
    400 
    401   StringRef getName() const {
    402     return FunctionDeclaration->getValueAsString("Name");
    403   }
    404   const Record *getDefaultReturnPredicate() const {
    405     return FunctionDeclaration->getValueAsDef("DefaultReturnValue");
    406   }
    407 
    408   const Record *getDeclaration() const { return FunctionDeclaration; }
    409   ArrayRef<const Record *> getDefinitions() const { return Definitions; }
    410   ArrayRef<OpcodeGroup> getGroups() const { return Groups; }
    411 };
    412 
    413 using ProcModelMapTy = DenseMap<const Record *, unsigned>;
    414 
    415 /// Top level container for machine model data.
    416 class CodeGenSchedModels {
    417   RecordKeeper &Records;
    418   const CodeGenTarget &Target;
    419 
    420   // Map dag expressions to Instruction lists.
    421   SetTheory Sets;
    422 
    423   // List of unique processor models.
    424   std::vector<CodeGenProcModel> ProcModels;
    425 
    426   // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
    427   ProcModelMapTy ProcModelMap;
    428 
    429   // Per-operand SchedReadWrite types.
    430   std::vector<CodeGenSchedRW> SchedWrites;
    431   std::vector<CodeGenSchedRW> SchedReads;
    432 
    433   // List of unique SchedClasses.
    434   std::vector<CodeGenSchedClass> SchedClasses;
    435 
    436   // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
    437   unsigned NumInstrSchedClasses;
    438 
    439   RecVec ProcResourceDefs;
    440   RecVec ProcResGroups;
    441 
    442   // Map each instruction to its unique SchedClass index considering the
    443   // combination of it's itinerary class, SchedRW list, and InstRW records.
    444   using InstClassMapTy = DenseMap<Record*, unsigned>;
    445   InstClassMapTy InstrClassMap;
    446 
    447   std::vector<STIPredicateFunction> STIPredicates;
    448   std::vector<unsigned> getAllProcIndices() const;
    449 
    450 public:
    451   CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
    452 
    453   // iterator access to the scheduling classes.
    454   using class_iterator = std::vector<CodeGenSchedClass>::iterator;
    455   using const_class_iterator = std::vector<CodeGenSchedClass>::const_iterator;
    456   class_iterator classes_begin() { return SchedClasses.begin(); }
    457   const_class_iterator classes_begin() const { return SchedClasses.begin(); }
    458   class_iterator classes_end() { return SchedClasses.end(); }
    459   const_class_iterator classes_end() const { return SchedClasses.end(); }
    460   iterator_range<class_iterator> classes() {
    461    return make_range(classes_begin(), classes_end());
    462   }
    463   iterator_range<const_class_iterator> classes() const {
    464    return make_range(classes_begin(), classes_end());
    465   }
    466   iterator_range<class_iterator> explicit_classes() {
    467     return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
    468   }
    469   iterator_range<const_class_iterator> explicit_classes() const {
    470     return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
    471   }
    472 
    473   Record *getModelOrItinDef(Record *ProcDef) const {
    474     Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
    475     Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
    476     if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
    477       assert(ModelDef->getValueAsBit("NoModel")
    478              && "Itineraries must be defined within SchedMachineModel");
    479       return ItinsDef;
    480     }
    481     return ModelDef;
    482   }
    483 
    484   const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
    485     Record *ModelDef = getModelOrItinDef(ProcDef);
    486     ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
    487     assert(I != ProcModelMap.end() && "missing machine model");
    488     return ProcModels[I->second];
    489   }
    490 
    491   CodeGenProcModel &getProcModel(Record *ModelDef) {
    492     ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
    493     assert(I != ProcModelMap.end() && "missing machine model");
    494     return ProcModels[I->second];
    495   }
    496   const CodeGenProcModel &getProcModel(Record *ModelDef) const {
    497     return const_cast<CodeGenSchedModels*>(this)->getProcModel(ModelDef);
    498   }
    499 
    500   // Iterate over the unique processor models.
    501   using ProcIter = std::vector<CodeGenProcModel>::const_iterator;
    502   ProcIter procModelBegin() const { return ProcModels.begin(); }
    503   ProcIter procModelEnd() const { return ProcModels.end(); }
    504   ArrayRef<CodeGenProcModel> procModels() const { return ProcModels; }
    505 
    506   // Return true if any processors have itineraries.
    507   bool hasItineraries() const;
    508 
    509   // Get a SchedWrite from its index.
    510   const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
    511     assert(Idx < SchedWrites.size() && "bad SchedWrite index");
    512     assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
    513     return SchedWrites[Idx];
    514   }
    515   // Get a SchedWrite from its index.
    516   const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
    517     assert(Idx < SchedReads.size() && "bad SchedRead index");
    518     assert(SchedReads[Idx].isValid() && "invalid SchedRead");
    519     return SchedReads[Idx];
    520   }
    521 
    522   const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
    523     return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
    524   }
    525   CodeGenSchedRW &getSchedRW(Record *Def) {
    526     bool IsRead = Def->isSubClassOf("SchedRead");
    527     unsigned Idx = getSchedRWIdx(Def, IsRead);
    528     return const_cast<CodeGenSchedRW&>(
    529       IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
    530   }
    531   const CodeGenSchedRW &getSchedRW(Record *Def) const {
    532     return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
    533   }
    534 
    535   unsigned getSchedRWIdx(const Record *Def, bool IsRead) const;
    536 
    537   // Return true if the given write record is referenced by a ReadAdvance.
    538   bool hasReadOfWrite(Record *WriteDef) const;
    539 
    540   // Get a SchedClass from its index.
    541   CodeGenSchedClass &getSchedClass(unsigned Idx) {
    542     assert(Idx < SchedClasses.size() && "bad SchedClass index");
    543     return SchedClasses[Idx];
    544   }
    545   const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
    546     assert(Idx < SchedClasses.size() && "bad SchedClass index");
    547     return SchedClasses[Idx];
    548   }
    549 
    550   // Get the SchedClass index for an instruction. Instructions with no
    551   // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
    552   // for NoItinerary.
    553   unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
    554 
    555   using SchedClassIter = std::vector<CodeGenSchedClass>::const_iterator;
    556   SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
    557   SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
    558   ArrayRef<CodeGenSchedClass> schedClasses() const { return SchedClasses; }
    559 
    560   unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; }
    561 
    562   void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
    563   void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
    564   void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
    565   void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
    566                           const CodeGenProcModel &ProcModel) const;
    567 
    568   unsigned addSchedClass(Record *ItinDef, ArrayRef<unsigned> OperWrites,
    569                          ArrayRef<unsigned> OperReads,
    570                          ArrayRef<unsigned> ProcIndices);
    571 
    572   unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
    573 
    574   Record *findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM,
    575                            ArrayRef<SMLoc> Loc) const;
    576 
    577   ArrayRef<STIPredicateFunction> getSTIPredicates() const {
    578     return STIPredicates;
    579   }
    580 private:
    581   void collectProcModels();
    582 
    583   // Initialize a new processor model if it is unique.
    584   void addProcModel(Record *ProcDef);
    585 
    586   void collectSchedRW();
    587 
    588   std::string genRWName(ArrayRef<unsigned> Seq, bool IsRead);
    589   unsigned findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead);
    590 
    591   void collectSchedClasses();
    592 
    593   void collectRetireControlUnits();
    594 
    595   void collectRegisterFiles();
    596 
    597   void collectOptionalProcessorInfo();
    598 
    599   std::string createSchedClassName(Record *ItinClassDef,
    600                                    ArrayRef<unsigned> OperWrites,
    601                                    ArrayRef<unsigned> OperReads);
    602   std::string createSchedClassName(const RecVec &InstDefs);
    603   void createInstRWClass(Record *InstRWDef);
    604 
    605   void collectProcItins();
    606 
    607   void collectProcItinRW();
    608 
    609   void collectProcUnsupportedFeatures();
    610 
    611   void inferSchedClasses();
    612 
    613   void checkMCInstPredicates() const;
    614 
    615   void checkSTIPredicates() const;
    616 
    617   void collectSTIPredicates();
    618 
    619   void collectLoadStoreQueueInfo();
    620 
    621   void checkCompleteness();
    622 
    623   void inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads,
    624                    unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices);
    625   void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
    626   void inferFromInstRWs(unsigned SCIdx);
    627 
    628   bool hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM);
    629   void verifyProcResourceGroups(CodeGenProcModel &PM);
    630 
    631   void collectProcResources();
    632 
    633   void collectItinProcResources(Record *ItinClassDef);
    634 
    635   void collectRWResources(unsigned RWIdx, bool IsRead,
    636                           ArrayRef<unsigned> ProcIndices);
    637 
    638   void collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads,
    639                           ArrayRef<unsigned> ProcIndices);
    640 
    641   void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM,
    642                        ArrayRef<SMLoc> Loc);
    643 
    644   void addWriteRes(Record *ProcWriteResDef, unsigned PIdx);
    645 
    646   void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx);
    647 };
    648 
    649 } // namespace llvm
    650 
    651 #endif
    652