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